2. 数据探索与清洗:缺失值处理策略(删除、填充、预测)、异常值检测与处理(IQR、Z-score、DBSCAN)、重复数据处理
在风控建模中,原始数据通常包含大量噪声、缺失和异常。直接使用未经清洗的数据建模会导致模型偏差、过拟合或泛化能力下降。本章系统讲解数据清洗的三大核心任务:缺失值处理、异常值检测与处理、重复数据处理,并提供可落地的策略选择与验证方法。
2.1 缺失值处理策略
缺失值在风控特征中普遍存在,原因包括用户未填写、数据采集失败、系统故障等。处理策略分为三类:删除、填充、预测。
2.1.1 缺失值处理策略对比
| 策略 | 方法 | 适用场景 | 风险与注意事项 |
|---|---|---|---|
| 删除 | 行删除、列删除 | 缺失比例极低(<5%)或缺失完全随机 | 删除过多会导致样本量不足,引入偏差 |
| 填充 | 均值/中位数/众数、前向/后向填充、常数填充 | 缺失比例适中(5%~30%),特征分布稳定 | 均值填充会降低方差,影响模型区分度 |
| 预测 | KNN、回归、随机森林、多重插补 | 缺失比例较高(>30%),特征间存在相关性 | 计算成本高,需避免过拟合与数据泄露 |
2.1.2 填充策略选择流程
决策要点:
- 先分析缺失机制:完全随机缺失(MCAR)、随机缺失(MAR)、非随机缺失(MNAR)。
- 对于风控评分卡,建议对连续变量使用中位数填充,对分类变量使用众数填充,并生成缺失指示变量。
- 预测填充需使用训练集拟合模型,避免测试集信息泄露。
# 示例:Python 中缺失值填充与指示变量生成
import pandas as pd
import numpy as np
# 中位数填充连续变量
df['income_filled'] = df['income'].fillna(df['income'].median())
# 生成缺失指示变量
df['income_missing'] = np.where(df['income'].isnull(), 1, 0)
# 众数填充分类变量
df['education_filled'] = df['education'].fillna(df['education'].mode()[0])
2.2 异常值检测与处理
异常值会扭曲统计分布、影响模型参数估计,尤其在逻辑回归和线性模型中表现明显。常用检测方法包括 IQR、Z-score 和 DBSCAN。
2.2.1 三种异常值检测方法对比
| 方法 | 原理 | 适用数据 | 优点 | 缺点 |
|---|---|---|---|---|
| IQR | Q1 - 1.5×IQR 到 Q3 + 1.5×IQR 之外 | 单变量、偏态分布 | 稳健、不受极端值影响 | 对正态分布不敏感 |
| Z-score | |Z| > 3 视为异常 | 单变量、近似正态分布 | 计算简单、有统计基础 | 对极端值敏感,小样本不稳定 |
| DBSCAN | 基于密度聚类,低密度点为异常 | 多变量、任意分布 | 可发现簇状异常、无需预设类别数 | 参数敏感(eps, min_samples) |
2.2.2 异常值处理策略
- 截尾(Winsorization):将异常值替换为边界值(如 1% 和 99% 分位数)。
- 删除:仅当异常值明显为录入错误或业务不可解释时使用。
- 单独编码:将异常值作为一个独立类别或分箱处理。
风控实践建议: 对于信用评分模型,建议对连续变量做分位数截尾(如 0.5%~99.5%),保留业务可解释的极端值(如高收入人群),避免过度清洗丢失信息。
# 示例:IQR 方法检测与截尾处理
Q1 = df['loan_amount'].quantile(0.25)
Q3 = df['loan_amount'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 截尾处理
df['loan_amount_winsor'] = df['loan_amount'].clip(lower=lower_bound, upper=upper_bound)
2.3 重复数据处理
重复数据会导致样本权重失衡、模型过拟合和评估指标失真。风控数据中重复可能来自数据合并、多次申请、系统重跑等。
2.3.1 重复数据检测与处理步骤
- 完全重复检测:所有字段完全一致的行,直接删除保留一条。
- 关键字段重复检测:基于身份证号、手机号、设备ID等唯一标识去重。
- 业务规则去重:如同一用户多次申请,保留最新一条或状态最完整的一条。
- 聚合去重:对重复记录做聚合统计(如取均值、最大值),生成新特征。
注意: 去重前务必确认业务含义。例如,同一用户在不同时间点的申请记录可能是正常的多笔贷款,不应简单删除。建议先按时间排序,再根据业务窗口期去重。
# 示例:基于身份证号去重,保留最新记录
df = df.sort_values('apply_date', ascending=False)
df_dedup = df.drop_duplicates(subset=['id_card'], keep='first')
2.4 数据清洗整体流程
下图展示了从原始数据到清洗后数据的完整处理链路,涵盖缺失值、异常值和重复数据的并行处理与验证。
2.5 清洗效果验证
数据清洗完成后,必须进行验证以确保清洗过程未引入新的问题。验证要点包括:
- 缺失率对比:清洗后各特征缺失率应为 0 或符合预期。
- 分布对比:使用 KS 检验或分位数对比,确保清洗前后数据分布未发生显著偏移。
- 重复率统计:确认重复行数归零或降至可接受范围。
- 业务规则校验:如年龄应在 0~120 之间,贷款金额应为正数等。
关键原则: 数据清洗应保持可追溯性。建议记录每一步清洗操作的参数、删除/填充的记录数,并保留清洗前后的数据快照,便于模型审计与迭代。