泰坦尼克:沉船事件背后的幸存者特征
下面这些动人心弦的话语,你认识几条?
- You jump, I jump.
- I’m the king of the world!
- A woman’s heart is a deep ocean of secrets.
以上内容出于电影《泰坦尼克号》,可能很多人都已经看过了。那么,你知道上面每一句话对应的含义吗?请在评论区分享给其他小伙伴,或者你可以再补充几条。
不过,我们今天并非是为了讨论这部电影,而是另有所图:根据历史记录的数据,对于泰坦尼克号上具有不同特征的乘客,他们幸存的概率表现不同。因此,秉持着科学严谨的态度,这篇博文将挖掘影响乘客生存几率背后的因素。
问题背景与数据集
问题背景:
1912 年 4 月 15 日,在她的处女航中,被广泛认为“永不沉没”的 RMS 泰坦尼克号在与冰山相撞后沉没。不幸的是,船上的每个人都没有足够的救生艇,导致 1502 名乘客和船员中有 2224 人死亡。
虽然生存下来有一些运气因素,但似乎某些群体比其他人更有可能生存下来。我们需要构建一个预测模型,使用乘客数据(即姓名、年龄、性别、社会经济阶层等)回答“什么样的人更有可能生存”这个问题。
数据集介绍
在这部分,首先对数据的缺失值情况进行统计,同时了解数据集结构。我们得到的数据集有两个:“train.csv”,“test.scv”.其次,统计数据分布情况以及乘客的不同特征与是否生还之间的联系。
(1)导入必要的库
用到matplotlib:绘图,missingno:查找缺失值,pandas,os:读文件与写文件操作
%config InlineBackend.figure_format = "retina"
%matplotlib inline
import os
import matplotlib
matplotlib.rcParams["axes.unicode_minus"] = False
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = 'SimHei'
import missingno as msno
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
train_data = r'./Data/train.csv'
test_data = r'./Data/test.csv'
数据集前5行:
train_data = pd.read_csv(train_data)
train_data.head()
结果:
(2)数据特征分析:
我们以train.csv文件为例,展示如何查找缺失值并对其进行可视化。
- 缺失值
# 创建一个 2x2 的子图布局
fig, axes = plt.subplots(1, 2, figsize=(10, 6))
msno.bar(train_data, ax=axes[0], color="lightblue")
custom_matrix(train_data, ax=axes[1], color=(0.25, 0.25, 0.5))
fig.suptitle("数据缺失值情况", fontsize=14)
# 自动调整子图布局
plt.tight_layout()
plt.show()
我们注意到Age,Cabin两列有很多缺失值。它们分别代表了:年龄,客舱编号;
简单分析及假设:年龄与生存概率有关,年轻人行动迅速,应对灾难时反映更灵敏;对于不同的客舱,那些离海面越近的舱室,在船体碰撞冰山后,海水首先灌进这些房间,因而其反应时间较短。猜测其生存概率相对会比较低。
2.性别与生存概率
统计不同性别的人数及比例:
women = train_data.loc[train_data.Sex == 'female']["Survived"]
rate_women = sum(women)/len(women)
print("number of women:",len(women))
print("% of women who survived:", rate_women)
可视化展示:
genders = ['men', 'women']
total_counts = [len(men), len(women)]
survived_counts = [sum(men), sum(women)]
survival_rates = [rate_men, rate_women]
# 设置条形图的宽度和位置
bar_width = 0.35
index = np.arange(len(genders))
# 设置图片清晰度
plt.rcParams['figure.dpi'] = 300
# 绘制总人数条形图
bars_total = plt.bar(index, total_counts, bar_width, label='Total', alpha=0.6)
# 绘制幸存人数条形图
bars_survived = plt.bar(index + bar_width, survived_counts, bar_width, label='Survived', alpha=0.6)
# 在条形图上标注生还概率
for i, rate in enumerate(survival_rates):
plt.text(index[i] + bar_width, min(total_counts[i], survived_counts[i]) + 5, f'{rate * 100:.2f}%', ha='center', va='bottom', fontsize=15)
# 设置图表标题和坐标轴标签
plt.title('Survival Statistics by Gender')
plt.xlabel('Gender')
plt.ylabel('Number of People')
3.分组密度曲线图
import seaborn as sns
sns.set_theme(font="KaiTi",style="whitegrid",font_scale=1.4)
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
sns.kdeplot(data=train_data,x="Age",hue="Survived",multiple="fill")
plt.subplot(1,2,2)
sns.kdeplot(data=train_data,x="Fare",hue="Survived",multiple="fill")
plt.tight_layout()
plt.show()
由上图,可知:训练数据集中男性数量几乎接近女性的两倍,但是其生存率(18.89%)却只有女性生存率(74.20%)的四分之一左右。这是为什么呢?
根据维基百科词条的细节描述,我们发现这艘巨大豪华的轮船实际上是依靠蒸汽机作为主要动力来源,我们在观看电影也能注意到这个细节。因此需要大量工人将煤炭等能源填入机器。根据记载泰坦尼克号试航时,船上有78名加煤工、加油工和生火员,以及41名船员。
上图中右侧的密度曲线图则反映了不同年龄段和票价区间的幸存概率曲线,可以观察到:低龄和高龄在遇到灾难时幸存的概率会大一些,当然也可能与这部分人较少也有关;而中等票价和高票价在逃生时具有一定优势。
(3) 数据特征解释:
列名 | 含义 |
---|---|
PassengerId | 乘客唯一编号 |
Survived | 生存情况(0 - 未存活,1 - 存活) |
Pclass | 船舱等级(1 - 一等舱,2 - 二等舱,3 - 三等舱 ) |
Name | 乘客姓名 |
Sex | 性别(male - 男性,female - 女性 ) |
Age | 年龄(可能有缺失值) |
SibSp | 船上兄弟姐妹或配偶数量 |
Parch | 船上父母或子女数量 |
Ticket | 船票编号 |
Fare | 船票价格 |
Cabin | 客舱编号(可能有缺失值) |
Embarked | 登船港口 |
基于随机森林的预测分析
随机森林介绍:随机森林(Random Forest)是一种集成学习方法,属于监督学习算法,主要用于分类和回归任务。它通过构建多个决策树并结合它们的预测结果来提高模型的准确性和鲁棒性。
随机森林的核心思想
-
集成学习:随机森林是基于集成学习思想的算法,通过组合多个弱学习器(决策树)来构建一个强学习器。
每棵决策树独立训练,最终通过投票(分类任务)或平均(回归任务)来输出结果。
随机性: -
样本随机性:使用 Bootstrap 方法(有放回的随机抽样)从训练数据中生成多个子样本,每个子样本用于训练一棵决策树。
-
特征随机性:在每棵树的节点分裂时,随机选择部分特征进行分裂,而不是使用所有特征。
from sklearn.ensemble import RandomForestClassifier
y = train_data["Survived"]
features = ["Pclass", "Sex", "SibSp", "Parch"]
X = pd.get_dummies(train_data[features])
X_test = pd.get_dummies(test_data[features])
model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=1)
model.fit(X, y)
predictions = model.predict(X_test)
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})
output.to_csv('./Output/submission.csv', index=False)
print("Your submission was successfully saved!")
总结:
以上分析和建模过程相对简略,后续会出一些更精巧的解决方案。我还想为大家推荐一部电影海上钢琴师,个人认为是一部不错的电影。
关于完整的程序和说明请移步我的仓库:sps.【该账号下所有的文章和对应的程序,数据都可以在gitee仓库上找到】
附录
[1].kaggle入门赛:titanic号沉船事件幸存者预测分析
[2].另一篇分类预测问题博文:KNN预测鸢尾花品类
[3].泰坦尼克号wiki百科:了解更多你想知道的细节