4. 数据探索与质量分析
在构建商户风险评分卡之前,必须对原始数据进行彻底的探索性数据分析(EDA)与质量审计。本章聚焦于数据清洗的三大核心任务:缺失值、异常值与重复值的检测与处理,并通过可视化手段理解各特征的数据分布形态。高质量的数据是评分卡模型稳定性和区分度的基石。
4.1 数据质量三要素检测
数据质量分析通常遵循“先检测、后处理”的原则。下表总结了三种常见数据质量问题的定义、检测方法与初步处理策略:
| 质量维度 | 定义 | 检测方法 | 初步处理策略 |
|---|---|---|---|
| 缺失值 | 数据记录中某个字段为空或为 NULL | isnull().sum() / 缺失率统计 |
删除(行/列)、均值/中位数填充、模型预测填充 |
| 异常值 | 显著偏离正常分布范围的极端值 | Z-Score、IQR 规则、箱线图 | 截尾(Winsorize)、删除、视为缺失值 |
| 重复值 | 完全相同的记录出现多次 | duplicated().sum() |
保留首条记录并删除其余重复项 |
关键指标: 对于商户风险数据,缺失率超过 50% 的特征通常建议直接删除;异常值检测中,IQR 方法(下界 Q1-1.5*IQR,上界 Q3+1.5*IQR)对非正态分布数据更为稳健。
4.2 缺失值检测与可视化
缺失值不仅会减少有效样本量,还可能导致模型估计偏差。我们首先通过代码统计每个特征的缺失数量与比例,然后使用矩阵热图直观展示缺失模式。
import pandas as pd
import missingno as msno
import matplotlib.pyplot as plt
# 假设 df 为商户风险数据集
missing_count = df.isnull().sum()
missing_ratio = df.isnull().mean()
# 输出缺失统计
missing_df = pd.DataFrame({'缺失数量': missing_count, '缺失比例': missing_ratio})
missing_df = missing_df[missing_df['缺失数量'] > 0].sort_values('缺失比例', ascending=False)
print(missing_df)
# 可视化缺失模式
msno.matrix(df, figsize=(12, 6), fontsize=10)
plt.title('商户数据缺失值矩阵图', fontsize=14)
plt.show()
缺失值矩阵图中,白色横线代表该位置数据缺失,密集的白色区域表示该特征缺失严重。对于缺失率较低的特征(如 < 5%),可采用中位数填充;对于缺失率中等(5%-30%)的特征,建议结合业务逻辑或使用模型(如 KNN、随机森林)进行预测填充。
4.3 异常值检测与箱线图分析
商户风险数据中的异常值可能代表欺诈交易、录入错误或极端经营状况。箱线图是检测连续变量异常值的经典工具,它基于四分位数自动标记离群点。
import seaborn as sns
# 选取关键连续特征绘制箱线图
features = ['交易金额', '交易笔数', '商户年龄(月)', '负债率']
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
for idx, feat in enumerate(features):
row, col = divmod(idx, 2)
sns.boxplot(y=df[feat], ax=axes[row, col], color='#3498db')
axes[row, col].set_title(f'{feat} 箱线图', fontsize=12)
axes[row, col].set_ylabel('')
plt.tight_layout()
plt.show()
处理建议: 对于“交易金额”等右偏分布特征,异常值通常位于上界之外。建议采用 Winsorize 方法,将超出 99% 分位数的值替换为该分位数,而非直接删除,以保留样本量。
4.4 重复值检测与去重
重复记录可能源于数据采集系统的重复上报或合并时的冗余。商户风险评分卡要求每条记录对应唯一的商户-时间窗口,因此必须严格去重。
# 检测重复行
dup_rows = df.duplicated().sum()
print(f"完全重复的记录数: {dup_rows}")
# 基于关键字段检测重复(如商户ID+月份)
key_dup = df.duplicated(subset=['商户ID', '数据月份'], keep='first').sum()
print(f"基于[商户ID, 数据月份]的重复记录数: {key_dup}")
# 去重操作
df_clean = df.drop_duplicates(subset=['商户ID', '数据月份'], keep='first')
注意: 去重前务必确认重复记录是否包含不同时间点的有效信息。若同一商户在同一月份出现多条记录,应检查是否为不同业务类型,必要时进行聚合而非简单删除。
4.5 数据分布可视化
理解特征的数据分布形态有助于后续的分箱策略与模型选择。我们通过直方图与密度图观察分布的中心趋势、离散程度与偏态特征。
# 绘制直方图与核密度估计
fig, axes = plt.subplots(2, 3, figsize=(16, 10))
features_plot = ['交易金额', '交易笔数', '商户年龄(月)', '负债率', '逾期次数', '信用评分']
for idx, feat in enumerate(features_plot):
row, col = divmod(idx, 3)
sns.histplot(df_clean[feat], kde=True, bins=50, color='#2ecc71', ax=axes[row, col])
axes[row, col].set_title(f'{feat} 分布图', fontsize=12)
axes[row, col].set_xlabel('')
plt.tight_layout()
plt.show()
分布可视化结果通常揭示以下规律:
- 右偏分布: 如“交易金额”、“交易笔数”,多数商户集中在低值区间,少数高值商户拉长右尾。此类特征适合进行对数变换或等频分箱。
- 近似正态分布: 如“商户年龄(月)”,可直接用于线性模型或等距分箱。
- 双峰或多峰分布: 如“负债率”,暗示数据中存在不同的商户子群,为后续分群建模提供了依据。
4.6 数据质量报告与决策
完成上述检测与可视化后,应汇总一份数据质量报告,作为特征筛选与分群策略的依据。报告应包含以下核心内容:
- 特征缺失率排名: 列出缺失率最高的前 10 个特征,并标注处理方式。
- 异常值特征清单: 标注每个连续特征的异常值数量与占比,以及采用的截尾分位数。
- 重复记录统计: 去重前后的样本量对比,确保去重逻辑合理。
- 分布形态总结: 对每个特征标注分布类型(正态、偏态、双峰等),为分箱方法选择提供参考。
实践要点: 数据清洗不是一次性工作。在后续特征工程与模型迭代中,应定期回溯数据质量,特别是当新增数据源或业务规则变更时。建议将数据质量检查脚本封装为自动化流水线,每次建模前自动生成质量报告。