4. Vintage 数据准备:所需数据字段、清洗与预处理、聚合与透视表构建
Vintage 分析的核心在于“按放贷批次追踪资产质量随账龄的演变”。数据准备阶段的质量直接决定后续归因分析的可靠性。本节将系统梳理所需字段、清洗规则与聚合方法,确保原始数据能够准确映射到 Vintage 曲线上。
4.1 所需数据字段清单
构建 Vintage 分析所需的最小数据集包含三类核心字段:标识字段、时间字段与状态字段。下表列出标准字段定义及示例:
| 字段类别 | 字段名称 | 字段说明 | 数据类型 | 示例值 |
|---|---|---|---|---|
| 标识字段 | loan_id | 借据唯一标识 | string | LOAN202503010001 |
| 标识字段 | user_id | 客户唯一标识 | string | USR10086 |
| 时间字段 | issue_date | 放贷日期(用于划分 Vintage 批次) | date | 2025-03-01 |
| 时间字段 | obs_date | 观测日期(账龄计算基准) | date | 2025-06-30 |
| 状态字段 | loan_status | 当前逾期状态(0-正常,1-逾期1-29天,2-逾期30-59天…) | int | 2 |
| 状态字段 | overdue_days | 实际逾期天数 | int | 45 |
| 衍生字段 | vintage_month | 放贷月份(由 issue_date 衍生) | string | 2025-03 |
| 衍生字段 | tenure_month | 账龄月数(obs_date - issue_date 取整) | int | 3 |
字段扩展建议: 若需进行坏样本归因,建议额外保留
product_type(产品类型)、channel(渠道)、loan_amount(放款金额)等维度字段,以便后续分层分析。
4.2 数据清洗与预处理
原始数据通常存在缺失、异常与逻辑冲突,必须经过以下清洗步骤才能进入聚合阶段:
- 缺失值处理: 删除
issue_date或loan_status为空的记录;若overdue_days缺失但loan_status非0,按状态区间中位数填充。 - 异常值过滤: 剔除
issue_date早于产品上线日期或晚于当前日期的记录;剔除overdue_days大于合同期限的异常数据。 - 逻辑校验: 确保
obs_date>=issue_date;若loan_status= 0(正常),则overdue_days必须为0。 - 账龄计算: 使用
DATEDIFF(month, issue_date, obs_date)或自定义月差函数生成tenure_month,注意跨年处理。 - 坏样本标记: 定义坏样本阈值(如逾期天数 >= 30 天),生成二值标签
is_bad(0/1)。
清洗后数据质量检查: 统计各 Vintage 批次的记录数、缺失率与异常率,确保每个批次至少有 100 笔以上有效借据,否则该批次应标记为“样本不足”并排除出分析。
4.3 数据聚合与透视表构建
清洗后的明细数据需按 Vintage 批次 × 账龄 进行聚合,生成用于绘制 Vintage 曲线的透视表。聚合逻辑如下:
- 分组键:
vintage_month(行索引)、tenure_month(列索引)。 - 聚合指标: 坏样本率 =
SUM(is_bad) / COUNT(loan_id);也可同时聚合逾期率、回收率等。 - 透视表结构: 行代表不同放贷月份,列代表账龄月数,单元格值为对应批次的坏样本率。
以下为 Python 伪代码示例:
import pandas as pd
# 假设 df 为清洗后的明细数据
pivot_table = df.pivot_table(
index='vintage_month',
columns='tenure_month',
values='is_bad',
aggfunc='mean'
)
# 填充缺失账龄(如某批次尚未观测到第12个月)
pivot_table = pivot_table.fillna(method='ffill', axis=1)
# 输出透视表
print(pivot_table.round(4))
生成的透视表示例如下(仅展示部分数据):
| vintage_month | M1 | M2 | M3 | M4 | M5 |
|---|---|---|---|---|---|
| 2025-01 | 0.0123 | 0.0234 | 0.0312 | 0.0356 | 0.0378 |
| 2025-02 | 0.0115 | 0.0218 | 0.0295 | 0.0332 | NaN |
| 2025-03 | 0.0130 | 0.0241 | 0.0308 | NaN | NaN |
注意: 透视表中的 NaN 表示该批次尚未达到对应账龄,不可用 0 填充,否则会严重低估坏样本率。建议使用前向填充(ffill)或直接保留 NaN,在绘图时自动跳过。
4.4 数据准备流程总览
以下 SVG 图展示了从原始数据到 Vintage 透视表的完整数据准备流程:
4.5 常见避坑指南
| 常见错误 | 后果 | 正确做法 |
|---|---|---|
| 使用放贷日期直接作为账龄计算基准 | 账龄偏差,Vintage 曲线错位 | 统一使用 obs_date - issue_date 计算实际账龄 |
| 用 0 填充未观测到的账龄 | 低估后期坏样本率,曲线异常下弯 | 保留 NaN 或使用前向填充 |
| 未剔除重复借据 | 同一笔贷款被多次计数,坏样本率失真 | 按 loan_id 去重,保留最新状态 |
| 聚合时使用逾期率而非坏样本率 | 无法区分“已还清”与“从未逾期”,归因失效 | 使用二值坏样本标签计算比率 |
效率提示: 若数据量超过百万级,建议在数据库层面完成聚合(如 SQL 的 GROUP BY + PIVOT),仅将透视表结果导入 Python/R 进行可视化,避免内存溢出。