准备入行数据分析领域,最近一直在学习数据分析的相关课程,刚刚将numpy以及pandas告一段落了,迫不及待的上Kaggle找个实战项目练练手,接下来将详细的过程记录如下。
文章目录
1.数据概览
先导入数据分析需要的基本库:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
读入数据,数据分为train.csv(训练集)和test.csv(测试集)两部分,其中测试集数据不带有标签,这里将两部分数据一次性读入并合并,将PassengerId作为数据的索引:
train_data = pd.read_csv('data/train.csv',index_col = 'PassengerId')
test_data = pd.read_csv('data/test.csv',index_col = 'PassengerId')
data_all = pd.concat([train_data,test_data],axis=0)
看一下数据的基本概况:
data_all.tail()
#1~891训练集,891~1309测试集
data_all.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1309 entries, 1 to 1309
Data columns (total 11 columns):
Age 1046 non-null float64
Cabin 295 non-null object
Embarked 1307 non-null object
Fare 1308 non-null float64
Name 1309 non-null object
Parch 1309 non-null int64
Pclass 1309 non-null int64
Sex 1309 non-null object
SibSp 1309 non-null int64
Survived 891 non-null float64
Ticket 1309 non-null object
dtypes: float64(3), int64(3), object(5)
memory usage: 122.7+ KB
各字段的含义如下:
'''
passengerId:乘客ID
survived:是否被救获
Pclass:乘客等级(舱位等级分为1/2/3等)
Name:乘客姓名
Sex:乘客性别
Age:乘客年龄
SibSp:siblings&spoused,该乘客在船上的堂兄弟妹/配偶人数
Parch:该乘客在船上的父母/孩子人数
Ticket:船票信息
Fare:票价
Cabin:客舱
Embarked:登船港口
出发地点:S=英国南安普顿Southampton
途径地点1:C=法国 瑟堡市Cherbourg
途径地点2:Q=爱尔兰 昆士敦Queenstown
'''
Cabin、Embarked、Age、Fare字段存在缺失值,Survived的缺失主要是由于我们将训练集与测试集整合在一起的缘故。接下来对缺失数据进行分析并填充。
2.缺失值处理
Cabin字段缺失数据1014条,缺失比例达77.5%,缺失比例过大,盲目填充可能会导致数据中的错误信息增加,本次分析将Cabin特征舍弃。接下来对Embarked、Fare、Age三个字段进行分别填充。
Embarked缺失值填充
原始数据中Embarked字段仅有两处缺失,将缺失的数据提取出来,看看其其他特征:
#查看Embarked缺失的两列情况
data_all.loc[data_all.loc[:,'Embarked'].isnull(),:]
缺失的两条数据ID分别为62和830,两个乘客的票号,舱位等级、票价及船舱号都相同,由此分析应该是一同上船的。现在以票价(Fare)和舱位等级(Pclass)作为突破口,假设同一处上船的票价相同。
#62号乘客和830号乘客的票价Fare都是80, Pclass都是1,那么先假设票价、客舱和等级相同的乘客是在同一个登船港口登船。
data_all.groupby(['Embarked','Pclass'])['Fare'].median()
Embarked Pclass
C 1 76.7292
2 15.3146
3 7.8958
Q 1 90.0000
2 12.3500
3 7.7500
S 1 52.0000
2 15.3750
3 8.0500
Name: Fare, dtype: float64
从上述分析可以看出,从C(法国 瑟堡市Cherbourg)登船的乘客票价的中位数与80最为接近,因此将Embarked的缺失字段用C填补。
#Embarked为C且Pclass为1的乘客的Fare中位数为80。因此可以将缺失的Embarked值设置为“C”
data_all['Embarked'].fillna('C',inplace = True)
Fare缺失值填充
Fare字段共缺失一条数据,看看缺失数据其他特征的情况:
#Fare值的缺失位置和相关信息
data_all.loc[data_all['Fare'].isnull(),:]
与之前的思路相同,查看从S(英国南安普顿Southampton)上船的3等舱的票价中位数:
data_all.groupby(['Embarked','Pclass'])['Fare'].median()
Embarked Pclass
C 1 78.2667
2 15.3146
3 7.8958
Q 1 90.0000
2 12.3500
3 7.7500
S 1 52.0000
2 15.3750
3 8.0500
Name: Fare, dtype: float64
从S港登船的乘客,票价的中位数为8.05,用该值填充缺失值:
#S登船港口上船且Pclass为3的乘客费用Fare的中位数为8.05,因此Fare的空缺值补充为8.05。
data_all['Fare'].fillna(8.05,inplace = True)
Age缺失值填充
先看一下未填充之前Age的分布情况:
#age原始数据的分布情况
data_all['Age'].hist(bins = 10,grid = False,density = True,figsize = (10,6))
此处,因为Age的缺失数据有263条,缺失比例为20.1%,如果全部简单的采用均值填补,会使得数据的分布发生较大的变化。因此,考虑使用随机森林对缺失值进行填补。这里选择Sex,Embarked,Fare,SibSp,Parch,Pclass作为缺失值填补的预测特征。首先对非数值型数据进行哑变量编码处理。
#age先考虑用随机森林填充
#选择的预测变量Sex,Embarked,Fare,SibSp,Parch,Pclass
from sklearn.preprocessing import OneHotEncoder
data_ = data_all.copy()
X_co = data_[['Sex','Embarked']]#需要编码的变量Sex,Embarked
enc = OneHotEncoder().fit(X_co)
result = OneHotEncoder().fit_transform(X_co).toarray()
enc.get_feature_names()
array(['x0_female', 'x0_male', 'x1_C', 'x1_Q', 'x1_S'], dtype=object)
创建预测需要的特征矩阵X:
#拼接填补缺失值用的特征矩阵
X = pd.concat([data_all.loc[:,['Fare','SibSp','Parch','Pclass']],pd.DataFrame(result,index = np.arange(1,1310),columns = ['female','male','C','Q','S'])],axis=1)
X.head()
创建预测标签Y
#标签
Y = data_all['Age']
划分训练集,测试集(其中Age字段没有缺失的行的集合,为训练集;Age字段存在缺失的行的集合为测试集)
#划分测试集,训练集
Y_tr = Y[Y.notnull()]
Y_te = Y[Y.isnull()]
X_tr = X.loc[Y_tr.index,:]
X_te = X.loc[Y_te.index,:]
导入随机森林模型,训练并输出预测结果
#随机森林填补缺失值
from sklearn