3. 缺失值处理(上):缺失值产生原因、缺失机制与删除法
在真实业务数据中,缺失值几乎是不可避免的。传感器断连、用户跳过填写、数据库合并错位、采集时间窗口不一致等场景都会导致数据矩阵中出现空值。如果不对缺失值做任何处理,大部分机器学习模型(如线性回归、SVM、神经网络)会直接报错或产生严重偏差。本章从缺失值的产生原因、统计机制和最简单的删除策略入手,为后续插补法打下理论基础。
3.1 缺失值的产生原因
缺失值并非随机出现,其背后通常对应着明确的业务或技术原因。归纳起来主要有以下四类:
| 原因类别 | 典型场景 | 示例 |
|---|---|---|
| 设备/系统故障 | 传感器离线、网络丢包、存储写入失败 | IoT 温度传感器在 03:00–03:15 无读数 |
| 人为遗漏 | 用户跳过必填项、问卷中途放弃、录入员疏忽 | 用户注册时未填写“职业”字段 |
| 数据合并/对齐 | 多源表 JOIN 后无匹配记录、时间窗口错位 | 用户行为表与订单表 LEFT JOIN 后订单字段为 NULL |
| 隐私/合规限制 | GDPR 脱敏、字段被授权屏蔽、敏感信息不采集 | 医疗数据中“患者姓名”被永久删除 |
实践建议:在开始缺失值处理前,务必与业务方确认缺失原因。设备故障导致的缺失通常可以用均值/中位数填充;而隐私屏蔽导致的缺失则必须保留 NULL 或使用特殊标记,不可随意插补。
3.2 缺失机制:MCAR / MAR / MNAR
缺失机制由 Rubin (1976) 提出,是选择缺失值处理方法的核心判断依据。三种机制的本质区别在于缺失概率是否依赖于数据本身。
核心定义速览:
- MCAR(完全随机缺失):缺失与否完全独立于所有变量(观测值 & 缺失值)。
- MAR(随机缺失):缺失与否依赖于其他已观测变量,但与自身真实值无关。
- MNAR(非随机缺失):缺失与否依赖于缺失变量自身的真实值。
3.3 如何判断缺失机制
实际数据中,MCAR 极少见,MNAR 最难验证。常用判断方法如下:
- 分组对比法(检验 MCAR):将数据按“是否缺失某字段”分为两组,对其他完整字段做 t 检验或卡方检验。若多数变量无显著差异,则近似 MCAR。
- 逻辑回归法(检验 MAR):以“是否缺失”为因变量,其他完整变量为自变量构建逻辑回归。若模型显著且存在强预测变量,则倾向于 MAR。
- 领域知识 + 敏感性分析(检验 MNAR):人为假设缺失值取极端值(如最大值/最小值),观察模型结果是否剧烈变化。若变化大,则可能存在 MNAR。
重要提醒:缺失机制无法被 100% 证明,只能通过统计检验和业务逻辑进行“合理推断”。在工业界,多数情况默认 MAR 假设,并采用多重插补或模型插补法。
3.4 删除法:行删除 vs 列删除
删除法是最简单、最直接的缺失值处理策略,适用于缺失比例低且机制为 MCAR 的场景。主要分为两种:
| 方法 | 操作 | 适用条件 | 优点 | 缺点 |
|---|---|---|---|---|
| 行删除 (Listwise Deletion) |
删除包含任意缺失值的整行样本 | 缺失率 < 5%,且 MCAR | 实现简单,保留完整数据矩阵 | 样本量锐减,若非 MCAR 则引入严重偏差 |
| 列删除 (Column Deletion) |
删除缺失率超过阈值的整列特征 | 缺失率 > 70%–80%,或该列信息量极低 | 快速降维,避免大量插补引入噪声 | 可能丢失重要特征,需业务确认 |
3.5 删除法的代码实现
以下代码展示在 Python 中使用 pandas 进行行删除和列删除的标准操作:
import pandas as pd
import numpy as np
# 构造示例数据
df = pd.DataFrame({
'feature_a': [1.0, 2.0, np.nan, 4.0, 5.0],
'feature_b': [10.0, np.nan, 30.0, 40.0, 50.0],
'feature_c': [100.0, 200.0, 300.0, np.nan, 500.0],
'label': [0, 1, 0, 1, 0]
})
print("原始数据形状:", df.shape)
# ===== 行删除 =====
df_row_del = df.dropna(axis=0) # 删除包含任何 NaN 的行
print("行删除后形状:", df_row_del.shape)
# ===== 列删除(缺失率 > 70%) =====
missing_rate = df.isnull().mean() # 每列缺失比例
cols_to_drop = missing_rate[missing_rate > 0.7].index.tolist()
df_col_del = df.drop(columns=cols_to_drop)
print(f"删除的列: {cols_to_drop}")
print("列删除后形状:", df_col_del.shape)
工程要点:
- 行删除前务必检查样本量是否仍满足模型训练需求(一般建议保留 > 1000 条或 > 10×特征数)。
- 列删除的阈值通常设为 70%–80%,但若该列是业务强相关特征(如用户 ID、时间戳),即使缺失率高也应保留或插补。
- 删除法仅适用于 MCAR 场景;若数据为 MAR 或 MNAR,删除法会导致估计有偏,应优先使用插补法(下一章详述)。
3.6 本章小结
- 缺失值产生原因包括设备故障、人为遗漏、数据合并和隐私限制,不同原因对应不同处理策略。
- 缺失机制分为 MCAR、MAR、MNAR,其中 MCAR 最理想但罕见,MNAR 最难处理,工业界通常默认 MAR 假设。
- 删除法是最简单的缺失值处理方式:行删除适用于低缺失率 MCAR 数据;列删除适用于高缺失率低信息量特征。
- 删除法会损失样本或特征,使用时必须评估对模型性能的影响,并优先考虑后续章节的插补方法。