Kaggle项目实践——Titanic: Machine Learning from Disaster

泰坦尼克号沉船事件是机器学习领域最经典的入门项目之一。Kaggle 上的 Titanic: Machine Learning from Disaster 竞赛,被无数人称为“机器学习的 Hello World”。

一、数据导入与清洗:让数据从 “杂乱” 变 “干净”

机器学习模型就像 “挑食的孩子”,只吃 “数值型、无缺失” 的数据。但原始数据往往充满 “漏洞”,所以第一步必须先做数据清洗

1.1 第一步:导入工具库与加载数据

# 导入必备库
import pandas as pd
import numpy as np

# 加载训练集(带生存标签)和测试集(需预测生存)
df_train = pd.read_csv('train.csv')  # 891条数据,含Survived列(1=幸存,0=遇难)
df_test = pd.read_csv('test.csv')    # 418条数据,无Survived列

1.2 第二步:检查数据 “漏洞”—— 找缺失值

数据缺失是最常见的问题,我们先写一个函数,直观展示哪些列有缺失:

def show_missing(df, name="DataFrame"):
    # 统计每列缺失值数量
    missing = df.isnull().sum()
    # 只保留有缺失的列
    missing = missing[missing > 0]
    if len(missing) == 0:
        print(f"✅ {name} 中无缺失值")
    else:
        print(f"⚠️  {name} 中存在缺失值:")
        print(missing)

# 检查训练集和测试集
show_missing(df_train, "训练集")
show_missing(df_test, "测试集")

运行结果

⚠️  训练集中存在缺失值:
Age         177  # 177个乘客年龄缺失
Cabin       687  # 687个乘客船舱号缺失(占比77%)
Embarked      2  # 2个乘客登船港口缺失

⚠️  测试集中存在缺失值:
Age          86  # 86个年龄缺失
Fare          1  # 1个票价缺失
Cabin       327  # 327个船舱号缺失

看到这些缺失值,不能直接删数据(会浪费信息),需要针对性处理。

1.3 第三步:缺失值处理 —— 用 “合理逻辑” 补全数据

缺失值处理的核心原则:基于业务逻辑选择填充方式,避免 “随便填数”。

(1)年龄(Age):按 “头衔” 智能填充

直接用 “全体年龄中位数” 填充不合理(比如 “儿童” 和 “老人” 年龄差异大)。但姓名中藏着 “头衔”(如 Mr = 先生、Mrs = 夫人、Miss = 小姐、Master = 少爷),不同头衔的年龄分布很规律 —— 这是关键突破口!

# 1. 从姓名中提取头衔
def extract_title(name):
    if pd.isna(name):  # 极端情况:姓名为空(实际数据中没有)
        return 'Unknown'
    # 姓名格式如“Braund, Mr. Owen Harris”,按逗号和句号分割取“Mr”
    title = name.split(',')[1].split('.')[0].strip()
    # 只保留常见头衔,少见的(如 Sir、Lady)归为“Other”
    if title not in ['Mr', 'Mrs', 'Miss', 'Master']:
        return 'Other'
    return title

# 给训练集和测试集添加“头衔”列
df_train['Title'] = df_train['Name'].apply(extract_title)
df_test['Title'] = df_test['Name'].apply(extract_title)

# 2. 按头衔计算训练集的年龄中位数(用训练集数据,避免“数据泄露”)
title_age_median = df_train.groupby('Title')['Age'].median()
print("按头衔分组的年龄中位数:")
print(title_age_median)

# 3. 按头衔填充缺失年龄
for title in title_age_median.index:
    # 填充训练集
    df_train.loc[(df_train['Age'].isnull()) & (df_train['Title'] == title), 'Age'] = title_age_median[title]
    # 填充测试集(用训练集的中位数,保证数据一致性)
    df_test.loc[(df_test['Age'].isnull()) & (df_test['Title'] == title), 'Age'] = title_age_median[title]

运行结果

按头衔分组的年龄中位数:
Title
Master     3.5  # 少爷(儿童):3.5岁
Miss      21.0  # 小姐(青年女性):21岁
Mr        32.0  # 先生(成年男性):32岁
Mrs       36.0  # 夫人(成年女性):36岁
Other     42.0  # 其他头衔(如医生、军官):42岁

用对应头衔的年龄中位数填充,比 “全体中位数” 精准得多!

(2)登船港口(Embarked):用 “众数” 填充

Embarked是分类变量(S = 南安普顿、C = 瑟堡、Q = 昆士敦),缺失值用 “出现次数最多的值(众数)” 填充 —— 因为 “多数人的选择更可能接近真实情况”。

# 计算训练集Embarked的众数(mode()[0]取第一个众数,避免返回Series)
embarked_mode = df_train['Embarked'].mode()[0]
print(f"训练集登船港口众数:{embarked_mode}")

# 填充缺失值
df_train['Embarked'] = df_train['Embarked'].fillna(embarked_mode)
df_test['Embarked'] = df_test['Embarked'].fillna(embarked_mode)

运行结果训练集登船港口众数:S(大部分乘客从 S 港口登船)。

(3)票价(Fare):用 “中位数” 填充

Fare是数值变量,但可能有极端值(比如头等舱票价极高),用 “中位数” 填充比 “平均值” 更稳健(不受极端值影响)。这里用sklearn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值