4. 风险暴露数据清洗:缺失值处理、异常值检测与处理、数据标准化与归一化技术
在风险暴露评估与A/B测试实践中,原始数据几乎总是包含缺失值、异常值以及量纲不一致的问题。本章聚焦于数据清洗的三大核心环节:缺失值处理、异常值检测与处理、数据标准化与归一化。这些步骤直接影响后续风险模型的稳定性和A/B测试的统计效力。
4.1 缺失值处理
缺失值在风险数据中普遍存在,原因包括用户未填写、系统采集故障、数据合并丢失等。处理策略分为删除、填充和模型预测三类。
| 策略 | 方法 | 适用场景 | 风险提示 |
|---|---|---|---|
| 删除 | 行删除、列删除 | 缺失比例 < 5%,且随机缺失 | 可能损失样本量,引入偏差 |
| 固定值填充 | 均值、中位数、众数、常数 | 数值型特征,缺失比例 5%-20% | 降低方差,削弱特征区分度 |
| 前向/后向填充 | 时间序列相邻值填充 | 时序数据,如日交易量、点击流 | 依赖数据顺序,不适用于无序数据 |
| 模型预测 | KNN、回归、随机森林 | 缺失比例 > 20%,特征间相关性强 | 计算成本高,可能过拟合 |
实践建议:在A/B测试中,缺失值处理策略应在实验前统一确定,并保持实验组与对照组一致。切勿在实验过程中根据结果动态调整填充方式,否则会引入实验偏差。
4.2 异常值检测与处理
异常值在风险暴露数据中可能代表欺诈、极端风险事件或数据录入错误。检测方法需结合业务含义与统计分布。
4.2.1 常用检测方法
- Z-Score 法:假设数据服从正态分布,|Z| > 3 视为异常。适用于对称分布数据。
- IQR 四分位距法:低于 Q1 - 1.5×IQR 或高于 Q3 + 1.5×IQR 视为异常。对偏态分布更稳健。
- 孤立森林:基于随机森林的集成方法,适合高维数据,不依赖分布假设。
- DBSCAN 聚类:基于密度,将低密度区域的点标记为异常,适合发现局部异常。
4.2.2 处理策略
| 处理方式 | 操作 | 适用场景 |
|---|---|---|
| 截尾 | 将异常值替换为边界值(如 99% 分位数) | 保留样本量,避免极端值影响模型 |
| 删除 | 直接移除异常样本 | 确认异常为录入错误或不可恢复 |
| 单独标记 | 新增二值特征标记是否为异常 | 异常本身可能携带风险信息 |
| 分箱处理 | 将连续值离散化,异常值归入单独箱体 | 非线性关系,或异常值比例较高 |
注意:在A/B测试中,异常值处理必须在实验分组前完成,或至少保证处理逻辑在两组中完全对称。若仅在实验组中截尾异常值,会人为改变组间分布,导致效应估计偏差。
4.3 数据标准化与归一化
风险暴露数据通常包含不同量纲的特征(如年龄、收入、交易金额、信用分)。标准化与归一化将特征缩放到统一尺度,避免量纲差异主导模型训练或距离计算。
4.3.1 核心方法对比
| 方法 | 公式 | 输出范围 | 适用场景 |
|---|---|---|---|
| Min-Max 归一化 | X' = (X - X_min) / (X_max - X_min) | [0, 1] | 数据有明确边界,如评分、百分比 |
| Z-Score 标准化 | X' = (X - μ) / σ | 均值为0,标准差为1 | 数据近似正态分布,存在异常值 |
| Robust 标准化 | X' = (X - Median) / IQR | 无固定范围 | 数据含较多异常值,分布偏态 |
| MaxAbs 归一化 | X' = X / |X_max| | [-1, 1] | 稀疏数据,如文本TF-IDF特征 |
4.3.2 在A/B测试中的特殊考量
- 分组独立拟合:标准化参数(均值、标准差、最小值、最大值)应在实验组和对照组中分别计算,避免信息泄露。
- 时间序列场景:使用滚动窗口或历史数据计算标准化参数,防止未来信息污染。
- 风险评分卡:归一化后特征可解释性下降,建议保留原始分箱映射表用于业务解读。
关键原则:标准化与归一化是数据预处理步骤,而非模型本身。在A/B测试中,若两组数据分布存在天然差异(如不同用户群),标准化后可能掩盖真实效应。建议在标准化前先进行分布一致性检验(如KS检验)。
4.4 代码示例:Python 实现
以下代码演示了缺失值填充、异常值检测与标准化处理的典型流程,适用于风险暴露数据预处理。
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from scipy import stats
# 示例数据
df = pd.DataFrame({
'age': [25, 30, np.nan, 35, 40, 28, 32, np.nan, 45, 38],
'income': [50000, 60000, 55000, 120000, 48000, 52000, 58000, 62000, 70000, 54000],
'credit_score': [650, 700, 680, 720, 600, 640, 690, 710, 660, 630]
})
# 1. 缺失值处理:用中位数填充
df['age'].fillna(df['age'].median(), inplace=True)
# 2. 异常值检测: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['income_outlier'] = ((df['income'] < lower_bound) | (df['income'] > upper_bound)).astype(int)
# 3. 异常值处理:截尾到边界
df['income_capped'] = df['income'].clip(lower=lower_bound, upper=upper_bound)
# 4. 标准化:Z-Score
scaler = StandardScaler()
df[['age_scaled', 'income_scaled', 'credit_scaled']] = scaler.fit_transform(
df[['age', 'income_capped', 'credit_score']]
)
# 5. 归一化:Min-Max
minmax_scaler = MinMaxScaler()
df[['age_norm', 'income_norm', 'credit_norm']] = minmax_scaler.fit_transform(
df[['age', 'income_capped', 'credit_score']]
)
print(df.head())
实践要点:
- 在A/B测试中,
fit_transform应在实验组和对照组上分别调用,避免使用全量数据拟合参数。 - 异常值标记特征(如
income_outlier)可作为风险模型的额外输入,提升对极端事件的敏感度。 - 标准化后的特征不再具有原始业务含义,建议保留原始特征用于业务报告。
4.5 本章小结
风险暴露数据清洗是A/B测试与风险评估的基石。缺失值处理需权衡样本量与偏差;异常值检测应结合业务逻辑与统计方法;标准化与归一化确保特征公平参与模型计算。在实际项目中,建议将清洗逻辑封装为可复用的预处理管道,并在实验设计阶段明确清洗策略,避免事后调整引入偏差。