泰坦尼克号乘客生存情况预测分析1

简介: 泰坦尼克号乘客生存情况预测分析1

背景描述

Titanic数据集在数据分析领域是十分经典的数据集,非常适合刚入门的小伙伴进行学习!

泰坦尼克号轮船的沉没是历史上最为人熟知的海难事件之一。1912年4月15日,在她的处女航中,泰坦尼克号在与冰山相撞后沉没,在船上的 2224 名乘客和机组人员中,共造成 1502 人死亡。这场耸人听闻的悲剧震惊了国际社会,从而促进了船舶安全规定的完善。造成海难失事的原因之一是乘客和机组人员没有足够的救生艇。尽管在沉船事件中幸存者有一些运气因素,但有些人比其他人更容易存活下来,究竟有哪些因素影响着最终乘客的生存与否呢?

数据说明

在该数据集中,共包括三个文件,分别代表训练集测试集以及测试集的答案

数据描述:

变量名称 PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
变量解释 乘客编号 是否存活 船舱等级 姓名 性别 年龄 兄弟姐妹和配偶数量 父母与子女数量 票的编号 票价 座位号 登船码头
数据类型 numeric categorical categorical String categorical categorical numeric numeric string numeric string categorical

显示详细信息

:以上数据类型均为经过预处理后的数据类型!

一 数据读取与分析

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('train.csv') # 训练集数据
data_test = pd.read_csv('test.csv') # 测试集数据
data_train.shape, data_test.shape, data_train.columns

可以看到训练集总共有12列891行数据,其中Survived字段表示的是乘客是否获救,其余都是乘客个人信息,包括:

  • Survived — 获救情况(二分类,因变量)
  • PassengerId — 乘客ID
  • Pclass — 乘客等级(1/2/3等舱位)
  • Name — 乘客姓名
  • Sex — 性别
  • Age — 年龄
  • SibSp — 堂兄弟/妹个数
  • Parch — 父母与小孩个数
  • Ticket — 船票信息
  • Fare — 票价
  • Cabin — 客舱
  • Embarked — 登船港口

2. 简单描述性分析

看一下数据类型及缺失情况

data_train.info()

  • 数据显示,训练数据集中共有891名乘客,12列特征,其中有三列数据存在缺失:
  • Age(年龄):只有714条完整记录,有177条记录缺失;
  • Cabin(客舱):只有204条乘客已知,有687条记录缺失,缺失较多!;
  • Embarked(登船港口):只有两条记录缺失;
  • 下面来看一下数据的描述性统计
data_train.describe()

  • 根据表格,我们可以得出一些基本信息:
  • Survived:大概有0.383838比例的人最后获救了;
  • Pclass: 2号和3号舱的人要比1号舱的人多;
  • Age:所有乘客的平均年龄大概再29.7岁,最小的乘客0.42岁,最大的乘客80岁;
  • Fare:平均票价在32元,最高的票价在512元;
  • 查看test数据集,看分布是否与训练集一致
data_test.describe()

  • 训练集和测试集大致的分布相差不大;

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(visible=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("人数")

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

  • 未能获救的人有500+,而获救的人大概有300+,不到人数的一半;
  • 三等舱乘客最多,接近500人,而一等和二等舱的乘客相对较少,都在200人左右;
  • 从年龄分布可以看出,遇难和获救的乘客年龄分布都比较离散,跨度大;
  • 三个不同舱的乘客年龄总体趋势大致相同,其中20岁左右的乘客主要集中再二三等舱,一等舱中40岁左右的最多;
  • 再登船港口中,其中S港口上传人数最多,有600+人,另外两个C和Q港口,都不到200人,要远远小于C港口;

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

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

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()

data_train[['Pclass', 'Survived']].groupby('Pclass').mean()

从图中可以看出,等级为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()

data_train[['Sex','Survived']].groupby('Sex').mean()

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

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

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

fig = plt.figure(figsize=(10,15))
fig.set(alpha=0.2)

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()

data_train[['Embarked','Survived']].groupby('Embarked').mean()

import seaborn as sns
import matplotlib.pyplot as plt

sns.catplot(x='Embarked', y='Survived', data=data_train, kind = 'point')
plt.title(u'各登录港口乘客的获救情况')
plt.show()

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

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

data_train['family'] = data_train['SibSp'] + data_train['Parch']
data_train['family']

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()

data_train[['family', 'Survived']].groupby('family').mean().plot.bar()

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

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()

data_train.Survived[data_train.Cabin.notnull()].value_counts(normalize=True)

data_train.Survived[data_train.Cabin.isnull()].value_counts(normalize=True)

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

3.7 缺失值处理

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

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

  • 如果缺值的样本占比较高,可以直接舍弃,以免作为特征加入,反倒带入噪声;
  • 如果缺值的样本适中,而该属性非连续值特征属性(比如类目属性),- 那就把NaN作为一个新类别,加到类别特征中
  • 如果缺值的样本适中,而该属性为连续值特征属性,可以尝试分桶处理;
  • 当缺失的样本并不是特别多的时候,我们可以试着根据已有的值,拟合一下数据,补充上。

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()

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

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

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

data_train.info()

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()

data_train['Age'].describe()

从上图可以看出,训练样本共有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

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['Name']

#方法一:
data_train['Title'] = data_train['Name'].apply(lambda x : x.split(',')[1].split('.')[0].strip())
pd.crosstab(data_train['Title'],data_train['Sex'])
#方法二:
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的关系

票价分布情况

plt.figure(figsize=(10, 8))
data_train['Fare'].hist(bins=70)

data_train.boxplot(column='Fare', by='Pclass', showfliers=False)

data_train['Fare'].describe()

绘制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. 小结

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

  • 舱位等级:舱位越高的获救的概率最大,并且随着等级的递减,比如一等舱就比二三等舱获救概率大;
  • 性别:女性的获救率远远高于男性;
  • 登船港口:C港口最高,Q次之,S港口最低;(需结合具体背景解释原因)
  • 携带家人数量:独自一人和亲友太多,存活率都比较低;
  • 客舱:缺失值较多,很难分析出有用信息,这里简单将缺失的看成一类,未缺失的看成一类;
  • 年龄:0到12岁儿童存活率最高,在50%左右,其次是少年,最低的是65岁到100岁的老年群体;
  • 称呼:不同称呼的乘客存活情况也不尽相同,存在显著差异;其中,Lady、Mlle、Mme、Ms、Sir以及the countess存活率均在100%;
  • 票价:生存者的平均票价要大于未生还者的平均票价;

本章只是涉及到泰坦尼克号的描述性统计分析,后续还会有关于此数据集的特征工程以及建模预测部分。

如果本文有存在不足的地方,欢迎大家在评论区留言。


相关文章
|
6月前
|
机器学习/深度学习 数据可视化 安全
Python随机森林、线性回归对COVID-19疫情、汇率数据预测死亡率、病例数、失业率影响可视化(下)
Python随机森林、线性回归对COVID-19疫情、汇率数据预测死亡率、病例数、失业率影响可视化
|
6月前
|
机器学习/深度学习 数据可视化 Python
Python随机森林、线性回归对COVID-19疫情、汇率数据预测死亡率、病例数、失业率影响可视化(上)
Python随机森林、线性回归对COVID-19疫情、汇率数据预测死亡率、病例数、失业率影响可视化
|
6月前
|
机器学习/深度学习 算法 安全
泰坦尼克号乘客生存情况预测分析2
泰坦尼克号乘客生存情况预测分析2
泰坦尼克号乘客生存情况预测分析2
|
6月前
|
机器学习/深度学习 算法 安全
泰坦尼克号乘客生存情况预测分析3
泰坦尼克号乘客生存情况预测分析3
|
6月前
|
算法 数据可视化 数据挖掘
R语言指数平滑预测法分析南京出租车打车软件空载率时间序列补贴政策可行性
R语言指数平滑预测法分析南京出租车打车软件空载率时间序列补贴政策可行性
|
机器学习/深度学习 算法 数据可视化
机器学习决策树算法泰坦尼克号乘客生存预测
机器学习决策树算法泰坦尼克号乘客生存预测
149 0
|
机器学习/深度学习 分布式计算 算法
应用分类算法,预测泰坦尼克号乘客幸存结果
应用分类算法,预测泰坦尼克号乘客幸存结果
|
机器学习/深度学习 数据采集 人工智能
泰坦尼克船员生存预测
泰坦尼克船员生存预测
115 0
泰坦尼克船员生存预测
|
安全 数据挖掘 C++
迄今最大规模新冠肺炎临床数据:男性病死率是女性3倍多,一人可传染3.77人
迄今最大规模新冠肺炎临床数据:男性病死率是女性3倍多,一人可传染3.77人
276 0
迄今最大规模新冠肺炎临床数据:男性病死率是女性3倍多,一人可传染3.77人