内容简介:利用随机森林算法预测 Titanic 乘客生还概率
数据清理
一、实验介绍
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 节中的得到的离群点是否应该删除
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- python 分析泰坦尼克号生还率
- 文科妹子都会用 GitHub,你这个工科生还等什么
- 顶尖AI技术人才稀缺,在校生还能追上这波浪潮吗?
- 算法工程师的数学基础:如何理解概率分布函数和概率密度函数
- 低概率问题分析解决
- 力扣 (1514):概率最大的路径
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。