赞
踩
#导入pandas库方便数据读取和预处理,导入os库方便修改工作路径
import os
import pandas as pd
#读取数据
os.chdir("F:/titianic_data")
train = pd.read_csv("raw/train.csv")
test = pd.read_csv("raw/test.csv")
train.shape
(891, 12)
train.head(3)#默认打印前5行
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
#查看有无缺失值
train.isnull().sum()
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
#查看数据维度和类型
train.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 891 entries, 0 to 890 Data columns (total 12 columns): PassengerId 891 non-null int64 Survived 891 non-null int64 Pclass 891 non-null int64 Name 891 non-null object Sex 891 non-null object Age 714 non-null float64 SibSp 891 non-null int64 Parch 891 non-null int64 Ticket 891 non-null object Fare 891 non-null float64 Cabin 204 non-null object Embarked 889 non-null object dtypes: float64(2), int64(5), object(5) memory usage: 83.6+ KB
#描述性统计分析
train.describe()
PassengerId | Survived | Pclass | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|---|
count | 891.000000 | 891.000000 | 891.000000 | 714.000000 | 891.000000 | 891.000000 | 891.000000 |
mean | 446.000000 | 0.383838 | 2.308642 | 29.699118 | 0.523008 | 0.381594 | 32.204208 |
std | 257.353842 | 0.486592 | 0.836071 | 14.526497 | 1.102743 | 0.806057 | 49.693429 |
min | 1.000000 | 0.000000 | 1.000000 | 0.420000 | 0.000000 | 0.000000 | 0.000000 |
25% | 223.500000 | 0.000000 | 2.000000 | 20.125000 | 0.000000 | 0.000000 | 7.910400 |
50% | 446.000000 | 0.000000 | 3.000000 | 28.000000 | 0.000000 | 0.000000 | 14.454200 |
75% | 668.500000 | 1.000000 | 3.000000 | 38.000000 | 1.000000 | 0.000000 | 31.000000 |
max | 891.000000 | 1.000000 | 3.000000 | 80.000000 | 8.000000 | 6.000000 | 512.329200 |
#查看字段的特征数量
train.nunique()
PassengerId 891
Survived 2
Pclass 3
Name 891
Sex 2
Age 88
SibSp 7
Parch 7
Ticket 681
Fare 248
Cabin 147
Embarked 3
dtype: int64
特征类型较少的,可视化分析
(1)定类数据:Embarked,Parch,Pclass,Sex,SibSp
(2)连续型数据:Age,Fare
特征类型较多的,后续处理再进行分析
(1)Name,Ticket,Cabin.
#合并train.csv以及test.csv进行下一步的数据缺失值处理
alldata = pd.concat([train,test],axis=0)
缺失值的处理方式有多种:
1.用某些集中趋势度量(均值、众数)进行填充
2.用统计模型来预测缺失值,例如决策树、随机森林RF、回归模型
3.删除缺失值
4.保留缺失值
第一个字段:Embarked
#Embarked字段
#观察数据的总体情况
print(train['Embarked'].value_counts())#训练集
print(test['Embarked'].value_counts())#测试集
S 644
C 168
Q 77
Name: Embarked, dtype: int64
S 270
C 102
Q 46
Name: Embarked, dtype: int64
对于Embarked类别型的特征字段,采用频率最高的特征值进行填充
# 忽略警告提示
import warnings
warnings.filterwarnings('ignore')
alldata.Embarked[alldata.Embarked.isnull()] = alldata.Embarked.dropna().mode().values
#还有三种表达方式
#alldata['Embarked'].fillna('S',inplace=True)
#alldata.loc[alldata.Embarked.isnull(),'Embarked']='S'
#alldata['Embarked'] = alldata['Embarked'].fillna(alldata['Embarked'].mode()[0])#通常默认使用第一个众数值
print(alldata['Embarked'].isnull().sum())#查看是否填补成功
0
第二个字段:Cabin
Cabin缺失比较严重,在train数据集中,891个观测值有687条观测值缺失,缺失比例达到 77%
处理这类数据方法之一是用一种特殊的字符来填充缺失值:把缺失值当成一类去对待,认为缺失本身是一种信息,应该保持它的独立性。
但这种方法比较适合类别变量,若要对连续变量使用该方法,需要首先对连续变量离散化,变成和类别变量一样的形式。
客舱位缺失可能代表这些人没有舱位,不妨使用’NO’来填充
alldata['Cabin'] = alldata['Cabin'].fillna('NO')
#其他表达方式
#alldata.loc[alldata.Cabin.isnull(),'Cabin'] = 'NO'
#alldata['Cabin'][alldata.Cabin.isnull()] = 'NO'
print(alldata['Cabin'].isnull().sum())#查看是否填补成功
0
第三个字段:Age
Age这个变量看上去比较重要,下面介绍几种填充方式
(1)采用与头衔相对应的年龄中位数进行填补
#不同方法得到结果有所不同,将数据拷贝一份,以防混淆不同方式得到的结果
title_alldata = alldata.copy()
train数据集中,891个观测值,姓名字段有891个不同的结果,直接拿来使用,没太大意义,但是值得注意的是姓名中有头衔存在,头衔又是身份地位的象征
有可能身份地位越高,越容易存活
import re
#提取头衔
title_alldata['title'] = title_alldata.Name.apply(lambda x:re.search('\w+\.',x).group()).str.replace('.','')
#查看一共有多少种不同的结果
title_alldata.title.unique()
array(['Mr', 'Mrs', 'Miss', 'Master', 'Don', 'Rev', 'Dr', 'Mme', 'Ms',
'Major', 'Lady', 'Sir', 'Mlle', 'Col', 'Capt', 'Countess',
'Jonkheer', 'Dona'], dtype=object)
头衔的解读:
Mr:既可以用于已婚男性,也可以用于未婚男性
Mrs:已婚女士
Miss:称呼未婚女士,有时也用于自己不了解的年龄较大的妇女
Master:男童或男婴
Don:大学老师
Rev:牧师
Dr:医生或者博士
Mme:女士
Ms:既可以用于已婚女士也可以用于未婚女士
Major:陆军少校
Lady:公侯伯爵的女儿
Sir:上级长官
Mile:小姐
Col:上校(常用于陆空军)
Capt:船长
Countess:伯爵夫人
Jonkheer:乡绅
头衔太多,最终决定再次分类,查看每个头衔与性别对应的人数
title_sex = pd.crosstab(title_alldata.title,title_alldata.Sex)
title_sex.T
title | Capt | Col | Countess | Don | Dona | Dr | Jonkheer | Lady | Major | Master | Miss | Mlle | Mme | Mr | Mrs | Ms | Rev | Sir |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Sex | ||||||||||||||||||
female | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 260 | 2 | 1 | 0 | 197 | 2 | 0 | 0 |
male | 1 | 4 | 0 | 1 | 0 | 7 | 1 | 0 | 2 | 61 | 0 | 0 | 0 | 757 | 0 | 0 | 8 | 1 |
决定将少数部分归为’Rare’(中文翻译:稀少的)
‘Mlle’、'Ms’用’Miss’代替
将’Mme’用’Mrs’代替
title_alldata['title'] = title_alldata['title'].replace(['Capt','Col','Countess','Don','Dr','Jonkheer','Lady','Major','Rev','Sir'],'Rare')
title_alldata['title'] = title_alldata['title'].replace(['Mlle','Ms'],'Miss')
title_alldata['title'] = title_alldata['title'].replace('Mme','Mrs')
#查看再次分类后,还有多少种不同的结果
title_alldata.title.unique()
array(['Mr', 'Mrs', 'Miss', 'Master', 'Rare', 'Dona'], dtype=object)
查看头衔与幸存的结果
import matplotlib.pyplot as plt
#绘制柱状图
title_survived = pd.crosstab(title_alldata['title'],title_alldata['Survived'])
title_survived.plot(kind='bar')
plt.xticks(np.arange(len(title_survived.index)),title_alldata.index,rotation = 360)
plt.title('Survived Status By Title')
Text(0.5,1,'Survived Status By Title')
幸存机会大对应的头衔:
Master,Miss,Mrs
幸存机会小对应的头衔:
Mr,Rare
train数据集中Age缺失值有177个,缺失比例约为20%,缺失数据也不少,而且Age在本次分析中比较重要(副船长当时坚持“小孩和女士先走”),因此缺失值不能删除也不能保留缺失值
方式之一:采用与头衔相对应的年龄中位数进行填补
#求出每个头衔对应的年龄中位数
age_title_median = title_alldata.groupby('title')['Age'].median()
#在当前表设置title为索引
title_alldata.set_index('title',inplace=True)
#在当前表填充缺失值
title_alldata.Age.fillna(age_title_median,inplace=True)
#重置索引
title_alldata.reset_index(inplace=True)
print(title_alldata['Age'].isnull().sum())
0
(2)采用均值进行填补
mean_alldata = alldata.copy()
print(alldata['Age'].isnull().sum())
263
mean_alldata['Age']=mean_alldata['Age'].fillna( mean_alldata['Age'].mean() )
print(mean_alldata['Age'].isnull().sum())
0
参考资料
http://www.cnblogs.com/star-zhao/p/9801196.html
https://mp.weixin.qq.com/s/lKEma5gAYvNw4lvEMu621g
https://www.kaggle.com/c/titanic/data
《Python机器学习及实战_从零开始通往KAGGLE之路》
如有违反或冒犯,请联系作者删除,QQ:2168849535。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。