缺失值有哪些处理方法?怎么选?
简化版
处理缺失值要先审计缺失比例、产生时点和可能机制(MCAR、MAR、MNAR),再按任务选删除、简单插补、模型/多重插补、原生缺失路由或缺失指示器。简单插补便宜但改变分布;复杂插补不保证更准,还必须折内拟合。缺失指示器可保留“是否缺失”的预测信号,却不能识别或修复 MNAR 带来的统计偏差。方案要用未见数据、缺失切片和线上一致性共同验收。
详细版
主流方法及取舍:
| 方法 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 删除行 | 丢掉含缺失的样本 | 简单、不引偏差(若 MCAR) | 缺失多时大量丢样本 |
| 删除列 | 丢掉缺失率过高的特征 | 去掉几乎没信息的列 | 可能丢有用特征 |
| 均值/中位数填充 | 数值列用统计量填 | 快、稳定 | 低估方差、扭曲分布 |
| 众数填充 | 类别列用最频繁值填 | 简单 | 加剧类别不平衡 |
| 模型/KNN/MICE 填充 | 用其他特征形成条件插补 | 可利用变量关系/表达不确定性 | 不保证更准,成本高且可能泄露 |
| 缺失标志 + 填充 | 填充同时加 is_missing 列 | 保留「缺失即信号」 | 增维 |
| 让模型自己处理 | XGBoost/LightGBM 内建缺失方向 | 无需额外处理 | 仅部分模型支持 |
关键原则:
- 先看缺失机制与任务:MCAR/MAR/MNAR 通常不能仅靠已观测数据被确定区分;删除或插补是否无偏依赖估计目标和假设,MNAR 往往需要机制模型与敏感性分析。
- 填充统计量只能在训练集上算,套到测试集,防数据泄露。
- 缺失本身可能是特征:如「收入未填」的人可能有共性,加 is_missing 列往往涨点。
完整版教学
一、第一步永远是「先搞清为什么缺」——三种缺失机制
盲目填充是新手最大的错。要先判断缺失的机制,因为它决定了「删除/填充会不会引入偏差」:
- MCAR(完全随机缺失):缺失指示与已观测、未观测数据都独立。完整案例分析在适当估计目标下可保持无偏但会损失效率;均值填充仍会扭曲方差和标准误,不能说任意简单填充都无偏。
- MAR(随机缺失):缺失概率和其他已观测特征有关,但和缺失值本身无关(如老年人更少填「收入」,但同龄同群体里填不填是随机的)。可以用其他特征来预测/填充,是模型填充的理论依据。
- MNAR(非随机缺失):即使给定已观测变量,缺失仍与未观测值相关(如高收入者更倾向隐瞒收入)。单加缺失标志不能恢复未观测分布;通常需要选择模型、模式混合模型、外部信息或不同假设下的敏感性分析。
面试高频追问「怎么处理缺失值」,答出「先判断缺失机制再决定方法」立刻和只会背「填均值」的人拉开档次。
二、删除法:简单但可能很贵
- 删行(listwise deletion):丢掉含缺失的样本。缺失很少且近似 MCAR 时常作为简单基线;是否可接受没有通用 5% 阈值,要看有效样本、群体覆盖和估计目标。
- 删列:缺失率高、采集不稳定且增量价值低时可删除。但没有通用 70% 或 80% 红线,应结合缺失指示的价值、成本和跨时间稳定性验证。
三、简单填充:快,但会悄悄扭曲数据
- 数值列:用均值或中位数填。有离群点或偏态时用中位数(更稳健),近似对称无离群点用均值。
- 类别列:用众数(最频繁类别)填。
代价(必须知道):
- 低估方差:把一堆缺失都填成同一个均值,人为制造了一个尖峰,数据方差被压小,后续基于方差的分析(如 PCA、置信区间)会失真。
- 破坏特征间相关性:填的值和其他特征无关,削弱了变量间的真实关系。
- 加剧类别不平衡:众数填充会让本就最多的类别更多。
所以简单填充是「快而糙」的方案,适合缺失少、要求不高的场景。
四、模型预测填充:更准,但更重
把「缺失值」当成要预测的目标,用其他特征来建模预测:
- KNN 填充:用特征空间里最近的 K 个邻居的值(均值/众数)填。
- 回归填充:用其他特征训练回归/分类模型预测缺失列。
- MICE(多重插补,Multiple Imputation by Chained Equations):迭代地用「其他所有特征」轮流预测每一个有缺失的特征,多轮收敛,还能生成多个插补数据集来反映填充的不确定性——统计上最严谨的方案之一。
它们能利用变量间关系,但单次回归插补可能低估不确定性,KNN 受尺度和距离影响,MICE 的结果依赖条件模型是否合理。代价是计算与治理更复杂;插补器必须在交叉验证每个训练折内拟合,验证/测试的特征和标签不能反向参与。用于统计推断的多重插补与用于线上预测的特征管线还应区分目标和部署可得性。
五、把「缺失」当成信息——最实用的一招
很多预测场景里,“是否缺失”本身可能有信号,但这并不能单凭相关性判定为 MNAR。例如某渠道系统故障同时导致字段缺失和高风险客群占比变化,指示器会捕捉关联,却未解释缺失机制。
正确做法:填充的同时,额外加一个二值标志列 is_missing。
原始: income = [5000, NaN, 8000, NaN]
处理后:
income = [5000, 中位数, 8000, 中位数] ← 保证数值可用
income_missing= [0, 1, 0, 1] ← 保留「缺失」这个信号
这样模型既能使用填充值,也能利用“该值原本缺失”的信息。这是常见且便宜的基线,但不保证提升,也不解决 MNAR 的可识别性;应通过消融、群体切片和漂移监控判断。
六、让模型自己处理缺失——树模型的特权
部分模型内建了缺失值处理,无需你手工填:
- XGBoost / LightGBM:训练时为每个分裂学习一个默认方向——遇到缺失值就走这个默认分支,相当于让模型自己学「缺失该归到哪边」。
- 因此用这类模型时,有时保留 NaN 交给模型比手工填充效果更好,还省事。
许多线性模型、SVM、神经网络层和 KNN 实现默认不接受 NaN,需要插补、掩码或选择明确支持缺失的实现;这是具体库能力,不是这些模型家族永恒统一的性质。
七、工程红线与常见坑
- 统计量只在训练集上算:均值/中位数/众数、KNN/回归填充模型,全部只用训练集拟合,再套到验证/测试集,否则数据泄露。
- 别在划分数据集之前全局填充——那是最隐蔽的泄露。
- 时间序列别用未来填过去:前向填充也只能在值在预测时已可见、业务语义允许延续且未超过最大陈旧期时使用;双向插值和全窗统计常会引入未来信息。
- 缺失值别用 0 乱填:0 在很多特征里是有意义的真实值(如「消费金额=0」),用 0 填 NaN 会污染语义。
八、用数字和工程流程校验理解
某列 1000 条记录缺失 20 条和缺失 800 条,处理策略不会相同。若收入缺失本身代表“用户拒绝填写”,仅用中位数填充会抹掉行为信号;常见做法是中位数填充再增加 income_missing 指示变量。
| 对象/方案 | 核心机制 | 选择或风险 |
|---|---|---|
| MCAR | 缺失与已观测/未观测值均无关 | 删除可能近似无偏但损失样本 |
| MAR | 缺失依赖已观测变量 | 条件建模或多重插补 |
| MNAR | 缺失依赖未观测值本身 | 需机制假设与敏感性分析 |
把面试题落到可执行流程:
audit missing pattern and timing
split data
fit imputer on training fold
transform + add indicator + monitor online
“模型能处理 NaN”不等于无需治理;训练与线上缺失语义、比例和默认分支必须一致。
九、常见误区与追问
- 误区:均值填充不会改变数据分布。 它压低方差、改变相关关系,并在大量缺失时制造人工峰值。
- 误区:缺失率高的特征一定要删除。 高缺失特征仍可能有强信号,需结合机制、稳定性和采集成本判断。
- 追问:为什么插补器只能在训练集 fit? 全量统计量包含验证和测试信息,会造成评估泄露。
- 追问:多重插补解决什么? 它生成多份合理插补以反映缺失不确定性,而不是把填充值当成确定事实。
- 追问:时间序列能直接前向填充吗? 只能使用预测时点之前的值,并限制间隔;反向填充通常会引入未来信息。
十、加强记忆
记忆主线是先审计“哪里缺、何时缺、为何可能缺”,再按预测或推断目标选择方案。MCAR 下完整案例可能无偏但损失效率;MAR 支持在正确条件模型下利用已观测变量插补;MNAR 不能靠一列 is_missing 自动修复,需要额外机制假设和敏感性分析。简单插补便宜但扭曲分布,模型/MICE 插补利用更多关系却依赖模型且成本更高,原生树缺失路由也仍要治理语义。所有拟合只在训练折进行,时间数据禁止未来反填,并通过缺失切片、漂移和线上一致性验收。