4. 数据清洗基础:缺失值与异常值处理
数据清洗是风控建模中最耗时但回报最高的环节。原始数据通常包含大量缺失值、异常值和噪声,直接建模会导致模型偏差、方差膨胀甚至完全失效。本章聚焦两类核心问题:缺失值与异常值,系统讲解其识别方法与处理策略。
4.1 缺失值处理
缺失值在风控数据中普遍存在,原因包括用户未填写、系统采集失败、数据源不完整等。处理前需先区分缺失机制:
| 缺失机制 | 含义 | 风控场景举例 |
|---|---|---|
| MCAR(完全随机缺失) | 缺失与任何变量无关 | 系统随机丢包导致部分用户学历字段缺失 |
| MAR(随机缺失) | 缺失与其他观测变量相关 | 高收入用户更倾向不填写负债金额 |
| MNAR(非随机缺失) | 缺失与缺失值本身相关 | 逾期用户故意不填写联系方式 |
实践建议:风控场景中 MAR 和 MNAR 更常见。直接删除含缺失值的样本可能导致严重的选择偏差,尤其在正样本(逾期用户)中缺失率往往更高。
4.1.1 删除法
删除法是最简单的处理方式,但需谨慎使用:
- 行删除(listwise deletion):删除含任意缺失值的样本。适用于缺失率低(<5%)且 MCAR 场景。
- 列删除:删除缺失率超过阈值(如 70%)的特征。适用于信息量极低的字段。
- 成对删除(pairwise deletion):在计算相关系数或协方差时仅使用有效观测对。适用于相关性分析阶段。
风险提示:在风控建模中,行删除可能导致样本量骤减,尤其当正样本本身稀缺时。建议删除前先计算删除后的正样本保留率。
4.1.2 填充法
填充法保留样本量,但会引入人为偏差。常用填充策略如下:
| 填充方法 | 适用场景 | 风控示例 |
|---|---|---|
| 均值/中位数填充 | 连续型变量,分布对称用均值,偏态用中位数 | 收入字段用中位数填充 |
| 众数填充 | 分类变量 | 职业类型用众数填充 |
| 固定值填充 | 明确业务含义的缺失 | “逾期天数”缺失填充为 0 |
| 前向/后向填充 | 时间序列数据 | 用户近 6 个月收入按月填充 |
| KNN 填充 | 变量间存在相关性 | 利用年龄、职业预测缺失收入 |
| 模型预测填充 | 缺失变量与其他变量强相关 | 用随机森林预测缺失的信用评分 |
4.1.3 模型预测填充
模型预测填充将缺失值作为目标变量,利用其他完整特征构建预测模型。核心步骤:
- 将数据分为:完整样本(无缺失)和缺失样本(目标变量缺失)。
- 在完整样本上训练回归/分类模型(如线性回归、随机森林、XGBoost)。
- 用训练好的模型预测缺失样本的目标值。
- 将预测值填入缺失位置。
# Python 示例:使用随机森林填充缺失值
from sklearn.ensemble import RandomForestRegressor
import pandas as pd
import numpy as np
def rf_impute(df, target_col, feature_cols):
"""
随机森林填充缺失值
:param df: 包含缺失值的数据框
:param target_col: 需要填充的目标列
:param feature_cols: 用于预测的特征列
"""
# 分离完整样本和缺失样本
complete = df[df[target_col].notna()]
missing = df[df[target_col].isna()]
# 训练模型
rf = RandomForestRegressor(n_estimators=100, random_state=42)
rf.fit(complete[feature_cols], complete[target_col])
# 预测并填充
df.loc[df[target_col].isna(), target_col] = rf.predict(missing[feature_cols])
return df
模型填充的陷阱:如果缺失变量与其他特征的相关性很弱(R² < 0.3),模型预测的填充值几乎等于随机噪声,此时不如直接用中位数填充。建议填充前先计算特征与目标变量的相关性。
4.2 异常值处理
异常值是指明显偏离数据分布的观测值。在风控中,异常值可能代表欺诈行为、数据录入错误或极端信用风险。处理前需先识别异常值:
- Z-Score 法:|Z| > 3 视为异常(正态分布假设)。
- IQR 法:低于 Q1 - 1.5×IQR 或高于 Q3 + 1.5×IQR 视为异常。
- 业务规则法:如年龄 > 120 岁、月收入 > 1 亿等。
风控特殊视角:异常值不一定是“错误”。例如,一笔 100 万的消费金额对普通用户是异常,但对高净值用户可能是正常行为。建议结合用户画像分层判断。
4.2.1 截尾法(Truncation)
截尾法直接删除异常值所在的样本。适用于异常值比例极低(<1%)且确认是数据错误的情况。
# IQR 法截尾示例
Q1 = df['income'].quantile(0.25)
Q3 = df['income'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 删除异常样本
df_clean = df[(df['income'] >= lower_bound) & (df['income'] <= upper_bound)]
4.2.2 盖帽法(Winsorization)
盖帽法将异常值替换为边界值,而非直接删除。保留样本量,同时限制极端值的影响。
| 盖帽方式 | 操作 | 风控场景 |
|---|---|---|
| 百分位盖帽 | 低于 P1 的替换为 P1,高于 P99 的替换为 P99 | 收入变量盖帽到 1% ~ 99% 分位 |
| IQR 盖帽 | 低于 Q1-1.5IQR 的替换为 Q1-1.5IQR,高于 Q3+1.5IQR 的替换为 Q3+1.5IQR | 负债率变量盖帽 |
| 业务盖帽 | 根据业务经验设定上下限 | 年龄上限设为 100 岁 |
# 百分位盖帽法示例
def winsorize_series(s, lower=0.01, upper=0.99):
"""
对序列进行百分位盖帽
"""
low = s.quantile(lower)
high = s.quantile(upper)
return s.clip(lower=low, upper=high)
df['income_winsorized'] = winsorize_series(df['income'])
4.2.3 分箱法(Binning)
分箱法将连续变量离散化为类别,天然消除极端值的影响。在风控中常用于构建评分卡模型。
- 等距分箱:按值域等间距划分。简单但可能造成箱内样本不均。
- 等频分箱:每箱包含相同数量的样本。适用于分布偏态的数据。
- 最优分箱:基于目标变量(如逾期标签)的分布进行分箱,最大化 IV 值或最小化卡方值。
分箱 vs 盖帽选择:如果后续模型是线性模型(如逻辑回归),盖帽法更合适,因为保留了数值的单调性;如果是树模型,分箱法更灵活,且能自动处理异常值。
4.3 处理策略对比与选择
实际风控项目中,缺失值和异常值往往同时存在。以下对比表帮助选择最优策略:
| 维度 | 缺失值处理 | 异常值处理 |
|---|---|---|
| 核心目标 | 保留样本量,减少偏差 | 消除极端值对模型的干扰 |
| 首选方法 | 中位数填充(连续)/ 众数填充(分类) | 盖帽法(保留样本)/ 分箱法(树模型) |
| 避免的方法 | 缺失率 > 50% 时仍用均值填充 | 直接删除大量异常样本导致样本失衡 |
| 模型影响 | 填充不当会引入噪声,降低模型区分度 | 不处理会导致模型过拟合极端值 |
| 风控特殊要求 | 缺失本身可能是有意义的特征(如“是否填写”作为新特征) | 异常值可能代表欺诈,需单独分析而非简单处理 |
关键原则:在风控建模中,缺失值和异常值的处理策略必须在训练集和测试集上保持一致。例如,训练集用中位数填充,测试集也必须用训练集的中位数,而不是测试集自己的中位数。否则会导致数据泄露,高估模型性能。
4.4 实战建议与避坑指南
- 缺失值作为新特征:在风控中,“是否缺失”本身可能是一个强预测变量。例如,用户不填写工作单位可能暗示其职业不稳定。建议创建 is_missing 二值特征。
- 异常值分层处理:不同客群的异常值阈值不同。例如,高净值用户的消费金额上限应远高于普通用户。建议按客群分层进行盖帽或分箱。
- 时间序列数据注意:对于时序特征(如近 3 个月收入),缺失值填充应使用前向填充而非全局均值,避免引入未来信息。
- 验证集独立处理:所有填充参数(均值、分位点、模型参数)必须从训练集计算,并直接应用于验证集和测试集。
最终检查清单:
✅ 缺失率 < 5%:行删除或中位数填充
✅ 缺失率 5%~30%:模型预测填充或 KNN 填充
✅ 缺失率 > 30%:考虑删除该特征,或保留缺失作为单独类别
✅ 异常值比例 < 1%:盖帽法(P1/P99)
✅ 异常值比例 1%~5%:分箱法或业务规则盖帽
✅ 异常值比例 > 5%:检查数据采集逻辑,可能不是异常而是正常分布
✅ 缺失率 < 5%:行删除或中位数填充
✅ 缺失率 5%~30%:模型预测填充或 KNN 填充
✅ 缺失率 > 30%:考虑删除该特征,或保留缺失作为单独类别
✅ 异常值比例 < 1%:盖帽法(P1/P99)
✅ 异常值比例 1%~5%:分箱法或业务规则盖帽
✅ 异常值比例 > 5%:检查数据采集逻辑,可能不是异常而是正常分布