内容字号:默认大号超大号

段落设置:段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

利用随机森林算法预测Titanic乘客生还概率

2018-01-11 17:50 出处:清屏网 人气: 评论(0

数据清理

一、实验介绍

1.1 实验内容

数据清洗是数据分析中非常重要的一部分,也最繁琐,做好这一步需要大量的经验和耐心。这门课程中,我将和大家一起,一步步完成这项工作。大家可以从这门课程中学习数据清洗的基本思路以及具体操作,同时,练习使用 Pandas 数据分析工具、Seaborn 统计分析可视化工具。

1.2 实验知识点

  • 离群点分析
  • 缺失值处理
  • 偏态分布数据处理

1.3 实验环境

  • Python 3.5
  • Xfce 终端

1.4 适合人群

难度中等,适合掌握 Python 基础,有意向学习数据分析的用户。

二、 实验步骤

2.1 环境准备

2.1.1 下载数据

$ wget http://labfile.oss.aliyuncs.com/courses/1001/train.csv #数据来源www.kaggle.com

2.1.2 环境配置

实验需要安装:

  • Jupyter Notebook
  • Virtualenv
  • Numpy
  • Pandas
  • Seaborn
  • Matplotlib

Virtualenv 用来隔离 python 执行环境,配置并进入 Virtualenv 环境:

$ sudo pip3 install virtualenv 
 $ virtualenv venv
 $ cd venv
 $ source bin/activate

注:更多关于 Virtualenv 的资料

Python 模块 Numpy, Pandas, Seaborn, Matplotlib 安装。(如果没有掌握以上工具,我建议通过理解后面的代码来学习使用这些工具。Seaborn 参考 Seaborn 手册

$ pip install numpy
 $ pip install pandas
 $ pip install matplotlib
 $ pip install seaborn

安装 Jupyter Notebook (一种交互式笔记本,支持多种编程语言)。

$ pip install jupyter

进入 Jupyter Notebook 交互界面。

$ jupyter notebook

稍等片刻,弹出浏览器并进入了 Jupyter Notebook,选择 New/Python 3(图1),进入交互界面(图2)。图 2 中 In[] 处输入代码,敲 Enter + Shift 执行代码。

2.2 数据清洗

2.2.1 检查数据

数据清洗的第一步是检查数据,我们通常会检查数据类别分布是否平衡、特征值的格式和分布、完整性(是否存在缺失数据)、合法性(是否存在不合法数据)、唯一性(数据是否重复)、一致性(不同特征内涵是否一样)等。

1. 准备数据

导入数据集

import pandas as pd
import numpy as np
import matplotlib as plt
import seaborn as sns
%matplotlib inline

data = pd.read_csv('~/train.csv')
data.head(5)

数据特征介绍

data.columns

我们导入的数据集 data,每行是一个训练样例(即游客),每列是该样例的特征。 其中 Suivived 代表游客是否存活(0 或 1),这是一个二分类问题(死亡 或 生存)。下面是各特征的详细说明:

  • PassengerId: 编号
  • Survived: 0 = 死亡,1 = 生存
  • Pclass: 船票级别 1 = 高级, 2 = 中等, 3 = 低等
  • Name: 名称
  • Sex: male = 男性,female = 女性
  • Age: 年龄
  • SibSp: 在Titanic 上的兄弟姐妹以及配偶的人数
  • Parch: 在Titanic 上的父母以及子女的人数
  • Ticket: 船票编号
  • Fare: 工资
  • Cabin: 所在的船舱
  • Embarked: 登船的港口 C = Cherbourg, Q = Queenstown, S = Southampton

2. 检查数据

检查数据的第一步是完整性。

len(data)

data.isnull().sum()

总共有 891 个游客的数据,177 个 Age 缺失,687 个 Cabin 缺失,2 个 Embarked 缺失。在后面我们需要用不同的方法补充这些数据。

然后,我们查看特征类别分布是否平衡。类别平衡指分类样例不同类别的训练样例数目差别不大。当差别很大时,为类别不平衡。当类别不平衡的时候,例如正反比为 9:1,学习器将所有样本判别为正例的正确率都能达到 0.9。这时候,我们就需要使用 “再缩放”、“欠采样”、“过采样”、“阈值移动” 等方法。

sns.countplot(x='Survived',data=data)

图的纵坐标表示在不同类别下的人数。相差不是特别大,我们认为属于类别平衡问题。

接下来,我们查看特征值分布和格式。在这里,我们观察每个特征特征值是什么格式,怎么分布,维度如何。

data.head(5)

  • Cabin, Embarked 等特征值数值化
  • Ticket 等高维数据降维处理并将特征值数值化
  • Fare,Age 等为连续数据,之后需要检查是否是偏态数据

接下来,删除无用的特征 PassengerId, Name。

data.drop(['PassengerId','Name'],axis=1,inplace=True)
data.columns

2.2.2 相关系数

参考 知乎关于相关系数、协方差的讨论

g=sns.heatmap(data[['Survived','SibSp','Parch','Age','Fare','Pclass']].corr(),cmap='RdYlGn',annot=True)

数值越大,相关性越大。Fare 和 Survived 有较大的正相关性。但这并不能说明其它的特征与 Survived 无关。

2.2.3 缺失值

根据不同的情况,可以使用中位数、平均值、众数填充,删除等方法处理缺失数据,更复杂的还有建模预测。

Age

作图 Age ~ Survived。年龄较小的孩子生存的几率大。补充缺失值后,我们必须检查是否对 Age ~ Survived 的性质产生影响。

Age0=data[(data['Survived']==0)&(data['Age'].notnull())]['Age']
Age1=data[(data['Survived']==1)&(data['Age'].notnull())]['Age']
g=sns.kdeplot(Age0,legend=True,shade=True,color='r',label='NotSurvived')
g=sns.kdeplot(Age1,legend=True,shade=True,color='b',label='Survived')

在 2.2.2 节中,根据 heatmap, Age 和 SibSp, Parch, Pclass 相关性高,我们再用箱型图直观感受下,以图形 Sex ~ Age, Pclass ~ Age 为例。

g=sns.factorplot(x='Sex',y='Age',data=data,kind='box')
g=sns.factorplot(x='Pclass',y='Age',data=data,kind='box')

上面两图说明男性和女性的年龄分布(指箱型图中的五条线,从上到下依次是最大值、四分位数、中位数、四分位数、最小值)基本一致,而购买不同等级票的人的年龄分布是不同的。所以,我们根据票的等级将数据分为不同的集合,再用缺失数据所在集合的平均值来进行填充,并检查填充后 Age ~ Survived 是否受到影响。

index = list(data[data['Age'].isnull()].index)
Age_mean = np.mean(data[data['Age'].notnull()]['Age'])
copy_data = data.copy()
for i in index:
    filling_age = np.mean(copy_data[(copy_data['Pclass'] == copy_data.iloc[i]['Pclass'])
                                    & (copy_data['SibSp'] == copy_data.iloc[i]['SibSp'])
                                    & (copy_data['Parch'] == copy_data.iloc[i]['Parch'])
                                    ]['Age'])
    if not np.isnan(filling_age):
        data['Age'].iloc[i] = filling_age
    else:
        data['Age'].iloc[i] = Age_mean
g = sns.kdeplot(Age0, legend=True, shade=True, color='r', label='NotSurvived')
g = sns.kdeplot(Age1, legend=True, shade=True, color='b', label='Survived')

Embarked

对于只有极少数缺失值的特征,我们可以选择删除该样例,使用众数、均值、中位数填充。

Cabin

对于这种复杂,高维的数据,我们需要挖掘它的规律。例如 Cabin 特征值由字母开头,判断船舱按字母分为A,B,C...

于是我们仅提取字母编号,降低维度。然后使用新的字母‘U’填充缺失数据。

data[data['Cabin'].notnull()]['Cabin'].head(10)

data['Cabin'].fillna('U',inplace=True)
data['Cabin']=data['Cabin'].map(lambda i: list(i)[0])
g = sns.factorplot(x='Cabin',y='Survived',data=data,ci=False,kind='bar',order=['A','B','C','D','E','F','T','U'])

g = sns.countplot(x='Cabin',hue='Pclass',data=data,order=['A','B','C','D','E','F','T','U'])

从上面的图中看得出,缺失数据的游客主要是三等舱的,并且这部分游客的生存率相对较低。

2.2.4 偏态分布

偏态分布的数据有时不利于模型发现数据中的规律,我们可以使用 Log Transformation 来处理数据,参考 Skewed Distribution and Log Transformation

Fare

g=sns.kdeplot(data[data['Survived']==0]['Fare'],shade='True',label='NotSurvived',color='r')
g=sns.kdeplot(data[data['Survived']==1]['Fare'],shade='True',label='Survived',color='b')

Fare 属于右偏态分布,Python 提供了计算数据偏态系数的函数 skew(), 计算值越大,数据偏态越明显。使用Log Transformation 后,我们看到计算值从 4.79 降到 0.44。

data['Fare']=data['Fare'].map(lambda i:np.log(i) if i>0 else 0)
g=sns.distplot(data['Fare'])
print('Skew Coefficient:%.2f' %(data['Fare'].skew()))

2.2.5 数值化和标准化

Ticket

Ticket 特征值中的一串数字编号对我们没有意义,忽略。下面代码中,我们用正则表达式过滤掉这串数字,并使用 pandas get_dummies 函数进行数值化(以 Ticket 特征值 作为新的特征,0,1 作为新的特征值)。参考 正则表达式

Ticket=[]
import re
r=re.compile(r'\w*')
for i in data['Ticket']:
    sp=i.split(' ')
    if len(sp)==1:
       Ticket.append('U')
    else:
       t=r.findall(sp[0])
       Ticket.append(''.join(t))
data['Ticket']=Ticket
data=pd.get_dummies(data,columns=['Ticket'],prefix='T')
data.columns

Sex

Sex 只有 male, female 两个特征值,用 0 替代 male, 1 替代 female。

data['Sex'].replace('male',0,inplace=True)
data['Sex'].replace('female',1,inplace=True)

2.2.6 离群点

离群点是显著偏离数据集中其余对象的点。离群点来源于操作失误,数据本身的可变性等。在不同的环境中,离群点扮演不同角色。例如一个人的年龄 300 岁,应予以删除,而某些环境中,我们却需要探测、研究离群点,例如欺诈检测。我们这里采用箱线法,检测特征 ['Age', 'Parch', 'SibSp', 'Fare']的离群点。参考 离群点和箱线法

from collections import Counter


def outlier_detect(n, df, features):
    outlier_index = []
    for feature in features:
        Q1 = np.percentile(df[feature], 25)
        Q3 = np.percentile(df[feature], 75)
        IQR = Q3 - Q1
        outlier_span = 1.5 * IQR
        col = ((data[data[feature] > Q3 + outlier_span]) |
               (data[data[feature] < Q1 - outlier_span])).index
        outlier_index.extend(col)
        print('%s: %f (Q3+1.5*IQR) , %f (Q1-1.5*QIR) )' %
              (feature, Q3 + outlier_span, Q1 - outlier_span))
    outlier_index = Counter(outlier_index)
    outlier = list(i for i, j in outlier_index.items() if j >= n)
    print('number of outliers: %d' % len(outlier))
    print(df[['Age', 'Parch', 'SibSp', 'Fare']].loc[outlier])
    return outlier


outlier = outlier_detect(3, data, ['Age', 'Parch', 'SibSp', 'Fare'])

这里我们检测出 4 个离群点,使用 drop 函数删除即可。

三、实验总结

本实验我们介绍了数据清洗的基本思路,大家不仅需要掌握数据清洗的基础知识,还要善于利用数据分析工具。同时,不同环境,数据清洗的方法不同,这就要求我们多做练习。

四、课后作业

  • 判断特征 Age 是否属于偏态分布
  • 补全 Cabin 缺失值后,对该特征进行数值化处理
  • 补全 Embarked 缺失值,对该特征进行数值化处理
  • 思考 2.2.6 节中的得到的离群点是否应该删除
分享给小伙伴们:
本文标签: 随机森林算法Titanic

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

CopyRight © 2015-2016 QingPingShan.com , All Rights Reserved.

清屏网 版权所有 豫ICP备15026204号