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 模型预测填充

模型预测填充将缺失值作为目标变量,利用其他完整特征构建预测模型。核心步骤:

  1. 将数据分为:完整样本(无缺失)和缺失样本(目标变量缺失)。
  2. 在完整样本上训练回归/分类模型(如线性回归、随机森林、XGBoost)。
  3. 用训练好的模型预测缺失样本的目标值。
  4. 将预测值填入缺失位置。
# 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 盖帽选择:如果后续模型是线性模型(如逻辑回归),盖帽法更合适,因为保留了数值的单调性;如果是树模型,分箱法更灵活,且能自动处理异常值。
数据清洗流程:缺失值与异常值处理 原始数据 缺失值处理 异常值处理 处理方法 • 删除法(行/列/成对删除) • 填充法(均值/中位数/众数/KNN) • 模型预测填充(RF/XGBoost) 处理方法 • 截尾法(直接删除异常样本) • 盖帽法(替换为边界值) • 分箱法(离散化消除极端值) 清洗后数据

4.3 处理策略对比与选择

实际风控项目中,缺失值和异常值往往同时存在。以下对比表帮助选择最优策略:

维度 缺失值处理 异常值处理
核心目标 保留样本量,减少偏差 消除极端值对模型的干扰
首选方法 中位数填充(连续)/ 众数填充(分类) 盖帽法(保留样本)/ 分箱法(树模型)
避免的方法 缺失率 > 50% 时仍用均值填充 直接删除大量异常样本导致样本失衡
模型影响 填充不当会引入噪声,降低模型区分度 不处理会导致模型过拟合极端值
风控特殊要求 缺失本身可能是有意义的特征(如“是否填写”作为新特征) 异常值可能代表欺诈,需单独分析而非简单处理
关键原则:在风控建模中,缺失值和异常值的处理策略必须在训练集和测试集上保持一致。例如,训练集用中位数填充,测试集也必须用训练集的中位数,而不是测试集自己的中位数。否则会导致数据泄露,高估模型性能。
盖帽法 vs 分箱法:异常值处理对比 盖帽法(Winsorization) 原始分布 异常 盖帽后 替换为边界值 优点:保留样本量,数值单调性不变 缺点:人为设定边界,可能掩盖真实异常 适用:线性模型、评分卡 分箱法(Binning) 原始分布 异常 分箱后(等频分箱) 箱1 箱2 箱3 箱4 优点:自动处理异常值,无需设定边界 缺点:丢失数值精度,分箱边界敏感 适用:树模型、逻辑回归(WOE编码)

4.4 实战建议与避坑指南

  • 缺失值作为新特征:在风控中,“是否缺失”本身可能是一个强预测变量。例如,用户不填写工作单位可能暗示其职业不稳定。建议创建 is_missing 二值特征。
  • 异常值分层处理:不同客群的异常值阈值不同。例如,高净值用户的消费金额上限应远高于普通用户。建议按客群分层进行盖帽或分箱。
  • 时间序列数据注意:对于时序特征(如近 3 个月收入),缺失值填充应使用前向填充而非全局均值,避免引入未来信息。
  • 验证集独立处理:所有填充参数(均值、分位点、模型参数)必须从训练集计算,并直接应用于验证集和测试集。
最终检查清单:
✅ 缺失率 < 5%:行删除或中位数填充
✅ 缺失率 5%~30%:模型预测填充或 KNN 填充
✅ 缺失率 > 30%:考虑删除该特征,或保留缺失作为单独类别
✅ 异常值比例 < 1%:盖帽法(P1/P99)
✅ 异常值比例 1%~5%:分箱法或业务规则盖帽
✅ 异常值比例 > 5%:检查数据采集逻辑,可能不是异常而是正常分布