4. 数据准备与预处理:贷后数据集字段说明与清洗
贷后预警模型的可靠性高度依赖数据质量。原始贷后数据通常包含大量缺失值、异常记录和噪声,直接建模会导致PSI(群体稳定性指标)计算失真。本节将系统讲解贷后核心字段的业务含义、缺失值处理策略以及异常值检测方法,为后续PSI实验评估奠定干净、一致的数据基础。
4.1 贷后数据集核心字段说明
贷后预警数据集通常包含三类字段:客户静态属性、贷后行为特征和逾期表现标签。下表列出最关键的字段及其业务含义:
| 字段名称 | 数据类型 | 业务含义 | 典型取值范围 |
|---|---|---|---|
overdue_days |
整型 | 当前逾期天数(M0=未逾期,M1=1-30天,M2=31-60天) | 0 ~ 180+ |
utilization_rate |
浮点型 | 额度使用率 = 当前已用额度 / 授信总额度 | 0.0 ~ 1.0(或0% ~ 100%) |
repayment_behavior |
分类型 | 最近一期还款行为:正常还款、最低还款、逾期未还、部分还款 | 4个类别 |
dpd_30_flag |
布尔型 | 过去30天内是否出现过≥1天逾期 | 0 / 1 |
current_balance |
浮点型 | 当前账户余额(本金+利息+罚息) | 0 ~ 授信额度×1.5 |
credit_limit |
浮点型 | 授信总额度 | 1000 ~ 500000 |
payment_history_12m |
字符串 | 过去12个月还款状态序列(如:NNNN1NNN2NN) | 由N/1/2/3/D组成 |
字段选择建议:PSI实验评估通常选择
overdue_days、utilization_rate和repayment_behavior作为核心监控变量。这三个字段对贷后风险变化最敏感,且在不同时间窗口内分布差异明显,适合用于群体稳定性检验。
4.2 缺失值处理策略
贷后数据的缺失通常由以下原因造成:客户信息未采集、数据同步延迟、业务系统升级导致历史字段为空。不同字段的缺失含义不同,需采用差异化处理策略。
4.2.1 缺失值分类与处理方法
| 字段 | 缺失率常见范围 | 缺失原因 | 推荐处理方法 |
|---|---|---|---|
overdue_days |
0% ~ 5% | 新开户客户尚未生成逾期记录 | 填充为0(视为未逾期) |
utilization_rate |
1% ~ 10% | 授信额度未同步或额度为0 | 若额度为0则填充0;否则用中位数填充 |
repayment_behavior |
2% ~ 8% | 还款日未到或数据未更新 | 填充为“未知”类别,或按最近一期已知行为前向填充 |
current_balance |
0% ~ 3% | 账户结清后余额未更新 | 填充为0 |
payment_history_12m |
5% ~ 20% | 开户不足12个月 | 用已有月份序列填充,不足部分标记为“N”(正常) |
4.2.2 缺失值处理代码示例
import pandas as pd
import numpy as np
# 加载贷后数据
df = pd.read_csv('post_loan_data.csv')
# 1. overdue_days:缺失填充为0
df['overdue_days'] = df['overdue_days'].fillna(0)
# 2. utilization_rate:额度为0时填充0,否则中位数填充
mask_zero_limit = df['credit_limit'] == 0
df.loc[mask_zero_limit, 'utilization_rate'] = 0.0
median_util = df.loc[~mask_zero_limit, 'utilization_rate'].median()
df['utilization_rate'] = df['utilization_rate'].fillna(median_util)
# 3. repayment_behavior:前向填充
df['repayment_behavior'] = df.groupby('customer_id')['repayment_behavior']\
.transform(lambda x: x.ffill())
# 4. current_balance:缺失填充为0
df['current_balance'] = df['current_balance'].fillna(0.0)
print("缺失值处理完成,剩余缺失率:", df.isnull().sum().sum())
避坑提示:切勿对所有字段统一使用均值填充。贷后数据中
overdue_days的均值可能为15天,但新客户缺失值填充15天会错误引入逾期信号。必须根据业务含义区分“真实缺失”与“业务含义上的零值”。
4.3 异常值检测与处理
贷后数据中的异常值会严重扭曲PSI的分箱边界和分布统计。常见的异常来源包括:数据录入错误(如逾期天数录入为999)、系统计算溢出(如额度使用率>1.0)、极端客户行为(如一次性大额还款导致余额为负)。
4.3.1 异常值检测方法
针对不同字段类型,采用差异化的检测方法:
- 连续型字段(overdue_days, utilization_rate, current_balance):使用IQR(四分位距)法或Z-score法。贷后数据通常右偏,IQR法更稳健。
- 分类型字段(repayment_behavior):检查是否出现未定义的类别值(如“已核销”但不在预设类别中)。
- 业务规则校验:例如
utilization_rate > 1.0或overdue_days < 0直接判定为异常。
4.3.2 IQR异常检测代码示例
def detect_outliers_iqr(series, multiplier=1.5):
"""
使用IQR方法检测异常值
参数:
series: pandas Series
multiplier: IQR倍数,贷后数据建议用1.5(保守)或3.0(宽松)
返回:
异常值布尔掩码
"""
Q1 = series.quantile(0.25)
Q3 = series.quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - multiplier * IQR
upper_bound = Q3 + multiplier * IQR
return (series < lower_bound) | (series > upper_bound)
# 检测逾期天数异常
outlier_mask = detect_outliers_iqr(df['overdue_days'], multiplier=1.5)
print(f"逾期天数异常值数量: {outlier_mask.sum()}")
# 检测额度使用率异常(业务规则+统计规则)
rule_outliers = (df['utilization_rate'] < 0) | (df['utilization_rate'] > 1.0)
stat_outliers = detect_outliers_iqr(df['utilization_rate'], multiplier=3.0)
combined_outliers = rule_outliers | stat_outliers
print(f"额度使用率异常值数量: {combined_outliers.sum()}")
4.3.3 异常值处理策略
| 异常类型 | 处理方式 | 适用场景 |
|---|---|---|
| 业务规则异常(如负值) | 直接删除或替换为边界值 | 录入错误、系统Bug |
| 统计异常但业务合理 | 保留或做封顶处理(Winsorize) | 极端逾期客户(如逾期180天) |
| 明显录入错误(如999) | 删除该记录 | 数据量充足时优先删除 |
| 分类型未知值 | 归为“其他”类别或按最近行为填充 | 新还款行为出现时 |
PSI实验特别提醒:异常值处理必须在同一时间窗口内统一规则。如果训练集和测试集采用不同的异常值阈值,PSI会因数据预处理不一致而产生虚假漂移。建议将异常值处理逻辑封装为函数,确保两个时间窗口执行完全相同的变换。
4.4 数据预处理流程总览
下图展示了贷后数据从原始表到PSI就绪数据集的完整预处理流程:
4.5 数据质量验证清单
完成预处理后,建议按以下清单逐项验证数据质量,确保PSI实验的输入数据可靠:
- 完整性检查:所有核心字段缺失率是否已降至0%(或可接受的业务阈值以下)。
- 范围检查:
overdue_days是否≥0且≤最大逾期天数;utilization_rate是否在[0,1]区间内。 - 唯一性检查:客户ID是否唯一,是否存在重复记录。
- 时间一致性:同一客户在不同时间窗口的字段逻辑是否自洽(如逾期天数不会随时间倒退)。
- 分布稳定性:预处理前后核心字段的分布形态是否发生非预期剧烈变化(可用KS检验快速验证)。
最佳实践:建议将数据预处理逻辑封装为
DataPreprocessor类,包含fit()和transform()方法。训练集上fit()学习填充值和异常阈值,测试集上直接transform(),确保PSI计算时两个时间窗口的预处理完全对齐。