泰坦尼克号乘客生存情况分析第一部分

第一部分 数据读取及探索性分析

哈喽,各位小伙伴。今晚是平安夜,就先祝大家平安夜快乐,永远平安健康。泰坦尼克号相信很多人都不陌生,今天呢,主要聊一聊之前做过的一个小项目,预测下泰坦尼克号乘客的生存情况,本项目共包括三大部分,分别为:数据读取与探索性分析特征工程处理建模预测,本篇主要介绍第一部分。废话不多说,直接开撸代码!

注意:关于数据集下载以及项目链接可以在公众号【数分小白龙】私信获取,或者在和鲸社区找到【经典案例之泰坦尼克号乘客生存情况预测分析】即可!

 

1. 数据读取

import warnings
warnings.filterwarnings("ignore")
import matplotlib.pyplot as plt
#设置中文编码和负号的正常显示
plt.rcParams['font.family']='Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False

import pandas as pd
import numpy as np

data_train = pd.read_csv('/home/mw/input/wlong9812/train.csv') # 训练集数据
data_test = pd.read_csv('/home/mw/input/wlong9812/test.csv') # 测试集数据
data_train.shape, data_test.shape, data_train.columns

2. 简单描述性分析

data_train.info() # 看一下数据类型及缺失情况

数据显示,训练数据集中共有891名乘客,12列特征,其中有三列数据存在缺失:

  1. Age(年龄):只有714条完整记录,有177条记录缺失;

  2. Cabin(客舱):只有204条乘客已知,有687条记录缺失,缺失较多!;

  3. Embarked(登船港口):只有两条记录缺失;

下面来看一下数据的描述性统计;

data_train.describe()

根据表格,我们可以得出一些基本信息:

  1. Survived:大概有0.383838比例的人最后获救了;

  2. Pclass: 2号和3号舱的人要比1号舱的人多;

  3. Age:所有乘客的平均年龄大概再29.7岁,最小的乘客0.42岁,最大的乘客80岁;

  4. Fare:平均票价在32元,最高的票价在512元; ....

3. 探索性分析

3.1 乘客不同特征的描述性统计

import matplotlib.pyplot as plt
%matplotlib inline

fig = plt.figure(figsize=(15,10))
fig.set(alpha=0.2) # 设定图标透明度

plt.subplot2grid((2,3),(0,0)) # 分为2行3列,从(0,0)算起
data_train.Survived.value_counts().plot(kind='bar')
plt.title('获救情况(1为获救)')
plt.ylabel('人数')

plt.subplot2grid((2,3),(0,1))
data_train.Pclass.value_counts().plot(kind="bar")
plt.ylabel("人数")
plt.title("乘客等级分布")

plt.subplot2grid((2,3),(0,2))
plt.scatter(data_train.Survived, data_train.Age)
plt.ylabel("年龄")                         
plt.grid(b=True, which='major', axis='y') # 绘制网格线
plt.title("按年龄看获救分布 (1为获救)")

plt.subplot2grid((2,3),(1,0), colspan=2)
data_train.Age[data_train.Pclass == 1].plot(kind='kde')  # 绘制密度图
data_train.Age[data_train.Pclass == 2].plot(kind='kde')
data_train.Age[data_train.Pclass == 3].plot(kind='kde')
plt.xlabel("年龄")
plt.ylabel("密度") 
plt.title("各等级的乘客年龄分布")
plt.legend(('头等舱', '2等舱', '3等舱'),loc='best') # 

plt.subplot2grid((2,3),(1,2))
data_train.Embarked.value_counts().plot(kind='bar')
plt.title("各登船口岸上船人数")
plt.ylabel("人数")

根据训练集数据绘制如上图所示,从图中我们可以得到一些信息:

  1. 未能获救的人有500+,而获救的人大概有300+,不到人数的一半;

  2. 三等舱乘客最多,接近500人,而一等和二等舱的乘客相对较少,都在200人左右;

  3. 从年龄分布可以看出,遇难和获救的乘客年龄分布都比较离散,跨度大;

  4. 三个不同舱的乘客年龄总体趋势大致相同,其中20岁左右的乘客主要集中再二三等舱,一等舱中40岁左右的最多;

  5. 再登船港口中,其中S港口上传人数最多,有600+人,另外两个C和Q港口,都不到200人,要远远小于C港口;

根据以上结论,提出一些假设:

1.不同舱位/乘客等级可能和财富/地位有关系,最后获救概率可能会不一样; 2.年龄对获救概率也一定是有影响的,毕竟背景知识提到,副船长还说『小孩和女士先走』呢; 3.获救概率与登船港口是不是有关系呢?也许登船港口不同,人的出身地位不同? ...

3.2 看看各乘客等级的获救情况

fig = plt.figure()
fig.set(alpha=0.2)  # 设定图表颜色alpha参数

Survived_0 = data_train.Pclass[data_train.Survived == 0].value_counts()
Survived_1 = data_train.Pclass[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u'未获救':Survived_0, u'获救':Survived_1})
df.plot(kind='bar', stacked=True)
plt.title(u'不同等级乘客获救情况')
plt.xlabel(u'乘客等级')
plt.ylabel(u'人数')
plt.show()

从图中可以看出,等级为1的乘客,获救的概率最大,并且随着等级的递减,获救的概率也是递减状态!所以,乘客等级这必然是一个影响乘获救的重要特征!!

3.3 查看各性别的获救情况

fig = plt.figure()
fig.set(alpha=0.2)

Survived_0 = data_train.Survived[data_train.Sex == 'male'].value_counts()
Survived_1 = data_train.Survived[data_train.Sex == 'female'].value_counts()
df = pd.DataFrame({u'男性':Survived_0, u'女性':Survived_1})
df.plot(kind='bar', stacked=True)
plt.title(u'不同性别乘客获救情况')
plt.xlabel(u'获救与否')
plt.ylabel(u'人数')
plt.show()

从图中可以看出,相对男性来说,女性的获救率远远高于男性,看来外国人还是比较践行女性优先的!所以,性别对于最终生存与否也是有非常重要影响的!

3.4 查看各登船港口的获救情况

泰坦尼克号从英国的南安普顿港出发,途径法国瑟堡和爱尔兰昆士敦,那么在昆士敦之前上船的人,有可能在瑟堡或昆士敦下船,这些人将不会遇到海难。

fig = plt.figure(figsize=(10,15))
fig.set(alpha=0.2)import seaborn as sns
sns.factorplot('Embarked','Survived',data=data_train)
plt.title(u'各登录港口乘客的获救情况')
sns.factorplot('Embarked','Survived',data=data_train)
plt.title(u'各登录港口乘客的获救情况')

Survived_0 = data_train.Embarked[data_train.Survived == 0].value_counts()
Survived_1 = data_train.Embarked[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u'未获救':Survived_0, u'获救':Survived_1})
df.plot(kind='bar', stacked=True)

plt.title(u'不同登船港口的乘客获救情况')
plt.xlabel(u'登船港口')
plt.ylabel(u'人数')
plt.show()

import seaborn as sns
sns.factorplot('Embarked','Survived',data=data_train)
plt.title(u'各登录港口乘客的获救情况')import seaborn as sns
sns.factorplot('Embarked','Survived',data=data_train)
plt.title(u'各登录港口乘客的获救情况')

可以看出,再不同港口上船,生还率不同,其中C港口最高,Q次之,S港口最低;

3.5 查看携带家人数量不同的获救情况

data_train['family'] = data_train['SibSp'] + data_train['Parch']
Survived_0 = data_train.family[data_train.Survived == 0].value_counts()
Survived_1 = data_train.family[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u'未获救':Survived_0, u'获救':Survived_1})
df.plot(kind='bar', stacked=True)
plt.title(u'携带不同家人数量的乘客获救情况')
plt.xlabel(u'携带家人数量')
plt.ylabel(u'人数')
plt.show()

可以看到,独自一人和亲友太多,存活率都比较低;

3.6 不同船舱类型的乘客获救情况

船舱的缺失值确实太多,有效值仅仅有204个,很难分析出不同的船舱和存活的关系,我们可以直接将该组特征丢弃掉,也可以简单地将数据分为是否有Cabin记录作为特征,将缺失数据归为一类,未缺失数据归为一类,一同跟与Survived进行分析;

is_null = data_train.Survived[data_train.Cabin.isnull()].value_counts()
not_null = data_train.Survived[data_train.Cabin.notnull()].value_counts()
df = pd.DataFrame({'为空':is_null, '非空':not_null}).transpose()
df.plot(kind='bar', stacked=True)
plt.title('按Cabin是否为空看获救情况')
plt.xlabel('Cabin是否为空')
plt.ylabel('人数')
plt.show()

可以看出,有cabin记录的乘客survival比例比无记录的高很多;

3.7 缺失值处理

这里只是为了进行探索性分析,具体更详细的数据处理见特征工程部分;

通常遇到缺值的情况,有下面几种处理方式:

  1. 如果缺值的样本占比较高,可以直接舍弃,以免作为特征加入,反倒带入噪声;

  2. 如果缺值的样本适中,而该属性非连续值特征属性(比如类目属性),那就把NaN作为一个新类别,加到类别特征中

  3. 如果缺值的样本适中,而该属性为连续值特征属性,可以尝试分桶处理;

  4. 当缺失的样本并不是特别多的时候,我们可以试着根据已有的值,拟合一下数据,补充上。

Embarked(共有三个上船地点),缺失俩值,可以用众数填充;

Cabin将缺失信息当做一个类目;

处理Embarked和数据

由于总共有1309条数据,Embarked只缺失两个,所以用众数填充即可;

data_train.Embarked[data_train.Embarked.isnull() == True] = data_train.Embarked.dropna().mode().values
data_train['Cabin'] = data_train.Cabin.fillna('U0') # 先简单填充Cabin

处理Age数据

facet = sns.FacetGrid(data_train,hue="Survived",aspect=4)
facet.map(sns.kdeplot,'Age',shade=True)
facet.set(xlim=(0,data_train['Age'].max()))
facet.add_legend()

  1. 通常使用回归、随机森林等模型来预测缺失属性的值。

  2. 经过分析:Age在该数据集里是一个相当重要的特征,所以保证一定的缺失值填充准确率是非常重要的,对结果也会产生较大影响。

  3. 这里使用随机森林预测模型,选取数据集中的数值属性作为特征(因为sklearn的模型只能处理数值属性,所以这里先仅选取数值特征,但在实际的应用中需要将非数值特征转换为数值特征);

from sklearn.ensemble import RandomForestRegressor

cols = ['Age', 'Survived', 'Pclass', 'SibSp', 'Parch', 'Fare']
age_df = data_train[cols]
X_train = age_df[age_df.Age.notnull()][cols[1:]]
y_train = age_df[age_df.Age.notnull()][cols[0]]
X_test = age_df[age_df.Age.isnull()][cols[1:]]

rfr = RandomForestRegressor(n_estimators=1000, n_jobs=-1) #n_estimators控制随机森林决策树的数量;n_jobs=-1会使用CPU的全部内核,大幅度提升速度
rfr.fit(X_train, y_train)
y_predict = rfr.predict(X_test)
data_train.loc[data_train.Age.isnull(),'Age'] = y_predict # 缺失值填充
data_train.info()

3.8 不同年龄下的平均生存率

plt.figure(figsize=(18,6))
data_train['Age_int'] = data_train.Age.astype(int)
rate = data_train[['Age_int', 'Survived']].groupby('Age_int', as_index=False).mean()
sns.barplot(x='Age_int', y='Survived', data=rate)
plt.show()

从上图可以看出,训练样本共有891份,平均年龄在29.5岁,标准差为13.7岁,最小年龄0.42岁,最大年龄80岁;根据年龄,可以将乘客划分为儿童、少年、成年、老年,分析四个群体的生还情况;

bins = [0, 12, 18, 65, 100]
data_train['Age_group'] = pd.cut(data_train['Age'], bins)
age_group_survived_rate = data_train.groupby('Age_group')['Survived'].mean()
age_group_survived_rate.plot(kind='bar')

从图中可以看出,0到12岁儿童的存活率是最高的,达到了50%左右,其次是少年群体,在45%以上,最低的就属于65岁到100岁的老年群体,存活率最低,在12%左右;所以看得出来,不管在哪,孩子永远都是第一要保护的对象;

3.9 不同称呼的乘客生存情况

通过观察名字数据,我们可以看出其中包括对乘客的称呼,如:Mr、Miss、Mrs等,称呼信息包含了乘客的年龄、性别,同时也包含了入社会地位等的称呼,如:Dr,Lady,Major(少校),Master(硕士,主人,师傅)等的称呼。

#方法一:
data_train['Title'] = data_train['Name'].apply(lambda x : x.split(',')[1].split('.')[0].strip())
#方法二:
# data_train['Title'] =data_train['Name'].str.extract(' ([A-Za-z]+)\.',expand=False)
pd.crosstab(data_train['Title'],data_train['Sex'])
# 不同称呼的生存率
data_train[['Title', 'Survived']].groupby('Title').mean().plot(kind='bar')

从图中可以看出,不同称呼的乘客存活情况也不尽相同,存在显著差异,其中称呼为Lady、Mlle、Mme、Ms、Sir以及the countess的人群的存活率最高,均达到了100%的存活率;

3.10 票价分布与Survived的关系

# 绘制survived与票价均值和方差的关系
fare_not_survived = data_train['Fare'][data_train['Survived'] == 0]
fare_survived = data_train['Fare'][data_train['Survived'] == 1]
 
average_fare = pd.DataFrame([fare_not_survived.mean(),fare_survived.mean()])
std_fare = pd.DataFrame([fare_not_survived.std(),fare_survived.std()])
average_fare.plot(yerr=std_fare,kind='bar',legend=False)

从图中可以看出,生存者的平均票价要大于未生还者的平均票价。

4. 小结

根据以上探索性分析,我们可以猜测出一些结论:

  1. 舱位等级:舱位越高的获救的概率最大,并且随着等级的递减,比如一等舱就比二三等舱获救概率大;

  2. 性别:女性的获救率远远高于男性;

  3. 登船港口:C港口最高,Q次之,S港口最低;(需结合具体背景解释原因)

  4. 携带家人数量:独自一人和亲友太多,存活率都比较低;

  5. 客舱:缺失值较多,很难分析出有用信息,这里简单将缺失的看成一类,未缺失的看成一类;

  6. 年龄:0到12岁儿童存活率最高,在50%左右,其次是少年,最低的是65岁到100岁的老年群体;

  7. 称呼:不同称呼的乘客存活情况也不尽相同,存在显著差异;其中,Lady、Mlle、Mme、Ms、Sir以及the countess存活率均在100%;

  8. 票价:生存者的平均票价要大于未生还者的平均票价;

好了,本小章节只是涉及到泰坦尼克号的描述性统计分析,后续还会有关于此数据集的特征工程以及建模预测部分,如果本文有存在不足的地方,欢迎大家私信,我会继续完善的;

  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数分小白龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值