Scikit-learn 缺失值处理:SimpleImputer 完整指南

Scikit-learn 缺失值处理:SimpleImputer 完整指南 一、为什么需要缺失值处理真实数据集普遍存在缺失值NaN。缺失值会导致机器学习模型训练报错大部分 estimator 不接受 NaN统计分析结果偏差缺失值不参与计算数据质量下降影响决策准确性处理策略对比策略适用类型优点缺点删除法任意简单直接丢失数据量小数据集不可用均值/中位数填充数值型保留样本量引入偏差扭曲分布众数填充类别型保留样本量可能加剧类别不平衡常数填充任意灵活可控需人工选择填充值模型预测填充任意最精确计算成本高实现复杂SimpleImputer覆盖了均值、中位数、众数、常数四种策略是工程实践中的首选方案。二、数据准备import pandas as pd import numpy as np # 构造含缺失值的测试数据集 data { size: [XL, L, M, np.nan, M, M], # 类别型有缺失 color: [red, green, blue, green, red, green], gender: [female, male, np.nan, female, female, male], # 类别型有缺失 price: [199.0, 89.0, np.nan, 129.0, 79.0, 89.0], # 数值型有缺失 weight: [500, 450, 300, np.nan, 410, np.nan], # 数值型有缺失 bought: [yes, no, yes, no, yes, no] } df pd.DataFrame(data)数据概览索引sizecolorgenderpriceweightbought0XLredfemale199.0500.0yes1Lgreenmale89.0450.0no2MblueNaNNaN300.0yes3NaNgreenfemale129.0NaNno4Mredfemale79.0410.0yes5Mgreenmale89.0NaNno缺失值检测# 统计每列缺失值数量 df.isnull().sum() # size 1 # color 0 # gender 1 # price 1 # weight 2 # bought 0三、四种填充策略详解策略 1均值填充mean适用场景数值型特征数据分布近似正态。from sklearn.impute import SimpleImputer 创建填充器strategymean 使用列均值填充 imputer SimpleImputer(missing_valuesnp.nan, strategymean) fit_transform 两步合一 fit() 计算 weight 列均值 (500450300410)/4 415.0 transform() 用 415.0 填充缺失位置 df[[weight]] imputer.fit_transform(df[[weight]])填充结果第 3 行和第 5 行的 weight 被 415.0 填充。查看填充统计值imputer.statistics_ # array([415.]) imputer.statistics_[0] array([415.]) imputer.statistics_[0] np.float64(415.0)关键点输入必须是二维结构df[[weight]]不能是df[weight]一维 Series均值仅基于非缺失值计算如果列全为 NaNfit_transform 会报错策略 2常数填充constant适用场景需要用特定业务含义值填充时如用 0 表示未测量、用 unknown 表示未知。# strategyconstant fill_value 指定填充值 imputer SimpleImputer( missing_valuesnp.nan, strategyconstant, fill_value99.0 # 用 99.0 填充 price 列缺失值 ) df[[price]] imputer.fit_transform(df[[price]])填充结果第 2 行 price 被 99.0 填充。imputer.statistics_ # array([99.0], dtypeobject)关键点fill_value可以是任意类型数值、字符串数值型用数值填充类别型用字符串填充statistics_返回dtypeobject与均值策略的float64不同策略 3众数填充most_frequent适用场景类别型特征或数值型离散值。# strategymost_frequent 使用列中出现次数最多的值 imputer SimpleImputer(missing_valuesnp.nan, strategymost_frequent) size 列中 M 出现 3 次最多NaN 被替换为 M df[[size]] imputer.fit_transform(df[[size]])填充结果第 3 行 size 被 M 填充。imputer.statistics_ # array([M], dtypeobject)关键点如果有多个值出现次数相同选第一个适用于类别型也可用于数值型离散值可能加剧类别不平衡已有 M 3 个填充后变 4 个策略 4批量填充字符串列适用场景一次性填充所有类别型列。# 重建数据集 df pd.DataFrame(data) 创建常量填充器用 empty 填充 imputer SimpleImputer( missing_valuesnp.nan, strategyconstant, fill_valueempty ) 自动筛选所有 object 类型的列 columns df.select_dtypes(include[object]).columns 选中: size, color, gender, bought 批量填充 df.loc[:, columns] imputer.fit_transform(df[columns])填充结果size 和 gender 列的 NaN 被替换为 empty。索引sizecolorgenderpriceweightbought0XLredfemale199.0500.0yes1Lgreenmale89.0450.0no2MblueemptyNaN300.0yes3emptygreenfemale129.0NaNno4Mredfemale79.0410.0yes5Mgreenmale89.0NaNno关键点select_dtypes(include[object])选中所有字符串列df.loc[:, columns]确保 inplace 赋值不触发 SettingWithCopyWarning一次 fit_transform 处理多列各列用同一个 fill_value四、进阶技巧技巧 1按非缺失子集计算统计量场景需要基于某列的非缺失值计算其他列的统计量。df pd.DataFrame(data) 筛选 weight 非缺失的行计算数值列均值 df[~df[weight].isnull()].select_dtypes(include[float]).mean() price 122.333333 weight 415.000000拆解说明# 步骤 1: df[weight].isnull() → 布尔序列True 表示缺失 # [False, False, False, True, False, True] 步骤 2: ~ 取反True 变 False筛选非缺失行 [True, True, True, False, True, False] 步骤 3: select_dtypes(include[float]) 选中 price 和 weight 列 步骤 4: .mean() 计算均值 price (199891297989)/5 122.33注意 price 第2行也缺失被排除 weight (500450300410)/4 415.0技巧 2fit 与 transform 分离场景训练集 fit测试集用训练集的统计量 transform避免数据泄露。from sklearn.model_selection import train_test_split # 划分训练集和测试集 train_df, test_df train_test_split(df, test_size0.3, random_state42) 训练集 fit计算均值 imputer SimpleImputer(strategymean) imputer.fit(train_df[[weight]]) 测试集 transform用训练集均值填充 避免测试集信息泄露到训练过程 test_df[weight] imputer.transform(test_df[[weight]])技巧 3Pipeline 集成场景将缺失值填充与模型训练组合成流水线。from sklearn.pipeline import Pipeline from sklearn.linear_model import LogisticRegression 构建 Pipeline先填充缺失值再训练模型 pipeline Pipeline([ (imputer, SimpleImputer(strategymean)), # 第一步均值填充 (classifier, LogisticRegression()) # 第二步训练模型 ]) 直接 fit/predict填充过程自动执行 pipeline.fit(X_train, y_train) predictions pipeline.predict(X_test)五、策略选型决策树缺失值类型 ├── 数值型 │ ├── 分布近似正态 → 均值填充mean │ ├── 有离群值 → 中位数填充median │ └── 离散值/业务含义明确 → 常数填充constant └── 类别型 ├── 分布均匀 → 众数填充most_frequent ├── 需要区分缺失与有效值 → 常数填充constant如 unknown └── 缺失比例高50%→ 考虑删除该列缺失比例阈值参考缺失比例推荐策略 5%均值/众数填充5% - 30%模型预测填充或常数填充 50%考虑删除该列或转为二值指示特征六、常见陷阱陷阱 1一维输入报错# ❌ 错误传入一维 Series imputer.fit_transform(df[weight]) # ValueError: Expected 2D array, got 1D array instead ✅ 正确传入二维 DataFrame imputer.fit_transform(df[[weight]])陷阱 2fit_transform 混用导致数据泄露# ❌ 错误测试集重新 fit imputer.fit(test_df[[weight]]) # 测试集信息泄露 # ✅ 正确用训练集的统计量 imputer.fit(train_df[[weight]]) imputer.transform(test_df[[weight]])陷阱 3众数填充加剧类别不平衡# size 列原始分布M3, L1, XL1 # 众数填充后M4, L1, XL1 # M 占比从 50% 升至 67%应对缺失比例高时改用常数填充并标记为独立类别。陷阱 4SettingWithCopyWarning# ❌ 可能触发警告 df[columns] imputer.fit_transform(df[columns]) ✅ 使用 loc 显式赋值 df.loc[:, columns] imputer.fit_transform(df[columns])七、速查表SimpleImputer 参数速查参数类型可选值默认值说明missing_values申明本文主要内容来源于ant-exercises-sklearn: scikit-learn 编程练习 100例是个人进行sklearn学习时的产物如有不适、请告之。