你能在泰坦尼克号上活下来吗-利用python进行探索性数据分析

一、背景

紧跟 AI 发展热潮,计划向 AI 应用工程师方向发力:

AI建议:Python 完整语法 + 实操练习 NumPy + Pandas + EDA 数据分析, 由此计划了五月的学习提升计划

五一假期啃完了廖雪峰的 Python3 入门教程,复工后利用每晚和周末的碎片时间,接着学习尚硅谷、黑马的 Python 系列课程,从基础语法一路学到数据分析。期间还借助 AI 出题刷题巩固知识点,不得不说,AI 加持下学习效率提升了不少,还能给提供情绪价值,动力满满。学习结束后,偶然从掘金上发现了

Kaggle泰坦尼克号数据集的入门竞赛练习题,内容十分贴合现阶段所学,便决定将它作为第一阶段学习的结业实战项目。

二、原始数据解读

1912 年 4 月 15 日,号称"永不沉没"的泰坦尼克号与冰山相撞后沉没,2224 名乘客和船员中,1502 人遇难

其包含的变量如下:

字段 含义 取值
PassengerId 乘客唯一编号 整数
Survived 是否存活(预测目标 0=死亡,1=幸存
Pclass 票舱等级(社会地位代理变量) 1=头等舱,2=二等舱,3=三等舱
Name 姓名(含头衔信息) 字符串
Sex 性别 male / female
Age 年龄 数值(含缺失值,以 .5 结尾表示估算值)
SibSp 同行的兄弟姐妹/配偶人数 整数
Parch 同行的父母/子女人数 整数
Ticket 票号 字符串
Fare 票价 数值
Cabin 客舱号 字符串(77% 缺失
Embarked 登船港口 C=Cherbourg,Q=Queenstown,S=Southampton

三、Step 1:数据导入与总览

导入相关库,导入训练集和测试集

python 复制代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')

plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

train = pd.read_csv('train.csv')
test  = pd.read_csv('test.csv')

print(train.head())
print(test.head())

print(train.shape, test.shape)   # ((891, 12), (418, 11))

print(train.isnull().sum(),test.isnull().sum())

总览一下数据

第一眼结论:

  • 训练集:891 行 × 12 列
  • 测试集:418 行 × 11 列(Survived 列正是我们要预测的)
  • 训练集中age,cabin,embarked有缺失值,测试集中age,cabin,Cabin有缺失值,我们待会儿对其进行相应处理

四、Step 2:缺失值可视化和清洗

ini 复制代码
# 缺失值热力图(直观查看缺失分布)
plt.figure(figsize=(14, 5))
sns.heatmap(train.isnull(), cbar=False, cmap="YlOrRd")
plt.title("缺失值分布热力图")
plt.show()
less 复制代码
 #Age 用中位数填充
train["Age"] = train["Age"].fillna(train["Age"].median())
# Embarked 用众数填充(仅2个缺失)
train["Embarked"] = train["Embarked"].fillna(train["Embarked"].mode()[0])
# Cabin 缺失极多,统一标记为 Unknown
train["Cabin"] = train["Cabin"].fillna("Unknown")

print("\n===== 清洗后缺失值检查 =====")
print(train.isnull().sum())

五、Step 3:探索性数据分析(EDA)

5.1 整体存活率

先看一下存活率:

ini 复制代码
f,ax=plt.subplots(1,2,figsize=(18,8))
train['Survived'].value_counts().plot.pie(explode=[0,0.1],autopct='%1.1f%%',ax=ax[0],shadow=True)
ax[0].set_title('Survived')
ax[0].set_ylabel('')
sns.countplot(x='Survived', data=train, ax=ax[1])
ax[1].set_title('Survived')
plt.show()

这批数据里一共 891 名乘客,只有约 350 人活了下来,存活率仅 38.4%,存活和遇难的人数差距很大。接下来我们会分析哪类乘客更容易活下来,现在先把 38.4% 当作整体的基础存活率来看,这是一个不平衡的分类问题。


5.2 性别 vs 存活(最重要的特征!)

ini 复制代码
font = FontProperties(fname=r"C:\Windows\Fonts\msyh.ttc", size=12)

sns.set(style="whitegrid")
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# 柱状图:不同性别的存活/死亡人数
sns.countplot(data=train, x='Survived', hue='Sex', ax=ax1)
ax1.set_title('不同性别的存活人数', fontproperties=font)

# 柱状图:不同性别的存活率
train.groupby('Sex')['Survived'].mean().plot.bar(ax=ax2)
ax2.set_title('不同性别的存活率', fontproperties=font)
ax2.set_ylabel('存活率', fontproperties=font)

plt.tight_layout()
plt.show()

震撼的结论:

性别 存活率
女性 约 74%
男性 约 19%

"妇女儿童优先" 不是传说------在数据面前,这是铁一般的事实。 如果你是男性,在泰坦尼克号上的存活概率不到 1/5。


5.3 舱位等级 vs 存活

ini 复制代码
# 柱状图:不同舱位的存活/死亡人数
sns.countplot(data=train, x='Survived', hue='Pclass', ax=ax1)
ax1.set_title('不同舱位的存活人数', fontproperties=font)

# 先计算不同舱位的存活率
survival_rate = train.groupby('Pclass')['Survived'].mean()
survival_rate.plot.bar(ax=ax2, color='skyblue')

ax2.set_title('不同舱位的存活率', fontproperties=font)
ax2.set_ylabel('存活率', fontproperties=font)

plt.tight_layout()
plt.show()
舱位 存活率
头等舱(1) 约 63%
二等舱(2) 约 48%
三等舱(3) 约 24%

金钱买不到一切,但能买到救生艇座位。 头等舱乘客的存活率是三等舱的 2.6 倍


5.4 性别 + 舱位交叉分析

ini 复制代码
sns.catplot(x='Pclass', y='Survived', hue='Sex', data=train, kind='bar')
plt.title('舱位 + 性别 对存活率的影响')
plt.show()

最惊人的发现:

  • 头等舱女性:约 96% 存活(91/94,仅 3 人不幸遇难)
  • 三等舱男性:约 12% 存活

你的命运,在登船那一刻就已经被舱位和性别决定了大半。


5.5 年龄 vs 存活

ini 复制代码
fig, ax = plt.subplots(figsize=(12, 5))
sns.histplot(data=train, x='Age', hue='Survived', bins=20, 
              multiple='stack', kde=True, palette='Set1', ax=ax)
ax.set_title('年龄分布与存活的关系')
plt.show()

观察结论:

  • 儿童(低龄段)存活率明显更高 → 再次验证"儿童优先"
  • 20-40 岁死亡率最高
  • 高龄乘客(>60 岁)存活率较低

5.6 登船港口 vs 存活

ini 复制代码
sns.countplot(data=train, x='Embarked', hue='Survived')
plt.title('登船港口 vs 存活')
plt.show()
港口 含义 存活率特点
C(Cherbourg,法国瑟堡) 最多头等舱乘客上船 存活率最高
S(Southampton,英国南安普敦) 大多数三等舱乘客上船 存活率最低
Q(Queenstown,爱尔兰皇后镇) 中等 介于两者之间

S 港存活率最低,并不是因为港口本身,而是因为从 S 港上船的三等舱乘客最多,看起来是港口的影响,实际是舱位等级在起作用。


5.7 票价 vs 存活

ini 复制代码
sns.histplot(data=train, x='Fare', hue='Survived', bins=30, 
              multiple='stack', kde=True)
plt.title('票价分布与存活的关系')
plt.show()
  • 高价票乘客存活率明显更高
  • 低票价乘客大规模遇难

5.8 相关性热力图

ini 复制代码
plt.figure(figsize=(10, 8))
sns.heatmap(train.corr(numeric_only=True), 
            annot=True, cmap='RdBu_r', center=0)
plt.title('特征相关性热力图')
plt.show()

关键相关性:

特征 与 Survived 的相关系数 解读
Pclass 约 -0.34 舱位等级越高(数字越小)越容易存活
Fare 约 0.26 票价越高越容易存活
Age 约 -0.0065 年龄影响较弱(单独看)
SibSp / Parch 接近 0 单独看影响不明显

六、Step 4:特征工程(让模型更懂数据)

6.1 从姓名中提取头衔(Title)

bash 复制代码
# 从姓名中提取头衔,如 "Mr.", "Mrs.", "Miss." 等
for df in [train, test]:
    df['Title'] = df['Name'].str.extract('([A-Za-z]+).', expand=False)

print(train['Title'].value_counts())

原始数据有 17 种头衔,需要合并:

bash 复制代码
for df in [train, test]:
    df['Title'] = df['Name'].str.extract('([A-Za-z]+).', expand=False)

title_mapping = {
    'Lady': 'Rare', 'Countess': 'Rare', 'Capt': 'Rare',
    'Col': 'Rare', 'Don': 'Rare', 'Dr': 'Rare',
    'Major': 'Rare', 'Rev': 'Rare', 'Sir': 'Rare',
    'Jonkheer': 'Rare', 'Dona': 'Rare',
    'Mlle': 'Miss', 'Ms': 'Miss', 'Mme': 'Mrs'
}

for df in [train, test]:
    df['Title'] = df['Title'].replace(title_mapping)

# 按头衔分组,计算存活率
title_survive = train.groupby('Title')['Survived'].agg(['count', 'mean'])
title_survive.columns = ['总人数', '存活率']
title_survive['存活率'] = title_survive['存活率'].apply(lambda x: f"{x:.2%}")

print(title_survive)

各头衔的存活率:

头衔 存活率 解读
Master(未成年男孩) 约 57.5% 儿童优先
Miss(未婚女性) 约 70.27% 女性优先
Mrs(已婚女性) 约 79.37% 女性优先
Mr(成年男性) 约 15.67% 最危险群体
Rare(特殊身份) 约 34.78% 军官/牧师等,情况复杂

6.2 构建家庭大小特征

bash 复制代码
for df in [train, test]:
    df['FamilySize'] = df['SibSp'] + df['Parch'] + 1
    df['IsAlone'] = (df['FamilySize'] == 1).astype(int)

train[['FamilySize', 'Survived']].groupby('FamilySize').mean().plot.bar()
plt.title('家庭人数 vs 存活率')
plt.show()

有趣的模式:

  • 独自旅行的人存活率最低(约 30%)
  • 中等家庭(2-4 人)存活率最高(约 50-60%)
  • 超大家庭(>4 人)反而存活率下降(可能因为行动不便)

七、关键结论:你能活下来吗

基于数据分析,你的存活概率可以这样估算:

你的情况 预估存活率 建议
头等舱 + 女性 > 95% 基本稳了,喝杯茶等救援
头等舱 + 男性 ~35% 有点悬,看运气
三等舱 + 女性 ~50% 还有机会,跟着人群走
三等舱 + 男性 < 15% 😬 自求多福......
儿童(任何舱位) ~60% 儿童优先,好好跟着大人
独自旅行 + 男性 ~18% 最危险的群体

数据告诉我们一个残酷的事实: 在泰坦尼克号上,你的性别和钱包,比其他重要得多

八、总结

最重要的收获不是模型,而是 EDA 的思维 : 在盲目跑模型之前,先问数据几个问题------你会发现, 数据自己就会告诉你答案

相关推荐
FBI HackerHarry浩1 小时前
在Python中TCP网络程序开发的步骤流程
运维·服务器·开发语言·网络·python·pycharm
Cosmoshhhyyy1 小时前
《Effective Java》解读第54条:返回零长度的数组或者集合,而不是null
java·开发语言·python
sleven fung1 小时前
GPT4All 本地大语言模型运行环境介绍
python·gpt·ai·langchain
zyl837211 小时前
Python 四大核心数据结构:列表、字典、元组、集合
数据结构·windows·python
燐妤1 小时前
现代 Python Web 框架:FastAPI实战指南
python·fastapi
清风一徐1 小时前
Python函数基础
开发语言·python
花落yu1 小时前
【无标题】
pytorch·python·深度学习
zhangfeng11331 小时前
htc 中minconda 明明安装了 Python 3.10显示 python 3.8 因为 `conda activate` 没有真正切换成功
开发语言·python·conda
m沐沐1 小时前
【机器学习】NLP---用 Python+TF-IDF 给《红楼梦》自动提取关键词
人工智能·python·机器学习·自然语言处理·nlp·中文分词·tf-idf