3. 数据准备与探索:数据源类型、质量检查与异常处理

授信分群评分模型的根基在于数据。本章将系统梳理三大核心数据源(人行征信、三方数据、行为数据),并建立一套标准化的数据质量检查与预处理流程。只有经过严格清洗的数据,才能支撑后续稳健的分群与评分。

3.1 三大数据源类型与特征

在消费金融与信贷场景中,建模数据通常来自以下三类渠道,每类数据在覆盖度、时效性、区分度上各有优劣。

数据源 典型字段 优势 局限性
人行征信 信贷历史、逾期记录、查询次数、负债率 权威性高、覆盖银行级借贷行为 覆盖人群有限(白户缺失)、更新频率低(月级)
三方数据 多头借贷、设备指纹、社交关系、消费偏好 补充白户画像、实时性强 数据质量参差、合规风险高、成本按调用计费
行为数据 APP点击流、还款操作、额度使用率、登录频次 高频动态、直接反映用户意图 需埋点采集、存在幸存者偏差(仅活跃用户)
实战建议: 在沙盘演练中,建议优先融合人行征信 + 行为数据构建基础模型,再引入三方数据做增量区分。避免一开始就堆砌过多变量,导致维度灾难。

3.2 数据质量检查四步法

数据质量检查不是一次性动作,而是贯穿整个数据准备阶段的迭代过程。以下四步法可确保数据进入建模环节前达到可用标准。

  1. 完整性检查: 统计每个字段的缺失率。对于缺失率 > 70% 的字段,直接剔除;对于 30%–70% 的字段,评估业务含义后决定是否保留并填充。
  2. 准确性检查: 验证字段值域是否合理。例如:年龄应在 18–100 之间,逾期天数不应为负数,利率不应超过 100%。
  3. 一致性检查: 跨字段逻辑校验。例如:贷款发放日期应早于首次逾期日期;婚姻状况为“已婚”时,配偶信息不应为空。
  4. 唯一性检查: 确认主键(如用户ID、申请单号)无重复。若有重复,需按业务规则去重(通常保留最新一条记录)。
质量检查清单示例(沙盘数据集):
  • 缺失率 > 50% 的字段:职业类型(58%)、居住时长(63%)→ 剔除
  • 异常值字段:年龄 = 0 或 200(共 12 条)→ 删除或按中位数填充
  • 逻辑冲突:放款日期 > 当前日期(3 条)→ 标记为数据录入错误,删除
  • 重复主键:用户ID 重复 7 条 → 保留最新申请记录

3.3 缺失值处理策略

缺失值处理没有万能公式,需结合字段含义与缺失机制选择方法。下表总结了常见场景下的推荐策略。

缺失机制 字段示例 推荐处理方法 注意事项
完全随机缺失 用户填写的兴趣爱好 直接删除该样本(若缺失比例 < 5%) 删除前确认样本量充足
随机缺失 收入字段(部分用户未填) 中位数/众数填充,或模型预测填充 避免使用均值填充(易受极端值影响)
非随机缺失 逾期天数(优质客户无逾期记录) 单独编码为“0”或“无逾期”类别 缺失本身即包含信息,不可随意填充
高缺失率字段 第三方征信评分(调用失败) 新增“是否缺失”二值特征 + 全局常量填充 保留缺失指示变量,避免信息丢失
避坑提醒: 切勿在未分析缺失原因的情况下统一填充 0 或均值。例如:将“逾期天数”缺失统一填充为 0,会错误地将优质客户与逾期客户混为一谈,严重破坏模型区分度。

3.4 异常值检测与处理

异常值通常源于数据录入错误、系统故障或极端但真实的用户行为。处理前需区分“真异常”与“业务合理极端值”。

常用检测方法:

  • 3σ 原则: 适用于近似正态分布的连续变量,超出均值 ± 3 倍标准差的值视为异常。
  • 箱线图法(IQR): 适用于偏态分布,低于 Q1 - 1.5×IQR 或高于 Q3 + 1.5×IQR 的值视为异常。
  • 业务规则法: 例如:单日申请次数 > 50 次(明显为机器行为),直接标记为欺诈样本。

处理策略优先级:

  1. 修正: 若能追溯源系统,直接修正错误值(如日期格式错误)。
  2. 截尾: 将异常值替换为 99% 或 1% 分位数,保留样本量。
  3. 删除: 仅当异常值比例 < 1% 且明显为录入错误时删除。
  4. 单独建模: 对于欺诈类异常,建议单独构建反欺诈规则或模型,不与正常样本混合训练。
数据准备与探索核心流程 人行征信 三方数据 行为数据 数据融合与对齐 完整性检查 准确性检查 一致性检查 唯一性检查 缺失值处理 删除 / 填充 / 单独编码 异常值处理 修正 / 截尾 / 删除 清洗后建模数据集

3.5 实战代码示例:缺失值与异常值处理

以下 Python 代码演示了在沙盘数据集上执行质量检查与清洗的典型流程,使用 pandas 和 numpy 实现。

import pandas as pd
import numpy as np

# 加载沙盘数据集
df = pd.read_csv('credit_sandbox.csv')

# ---------- 1. 缺失率检查 ----------
missing_ratio = df.isnull().mean().sort_values(ascending=False)
print("字段缺失率:\n", missing_ratio[missing_ratio > 0])

# 剔除缺失率 > 70% 的字段
high_missing_cols = missing_ratio[missing_ratio > 0.7].index.tolist()
df.drop(columns=high_missing_cols, inplace=True)
print(f"剔除高缺失字段:{high_missing_cols}")

# ---------- 2. 异常值检测(箱线图法) ----------
def detect_outliers_iqr(series):
    Q1 = series.quantile(0.25)
    Q3 = series.quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    return (series < lower_bound) | (series > upper_bound)

# 对年龄字段检测异常
age_outliers = detect_outliers_iqr(df['age'])
print(f"年龄字段异常值数量:{age_outliers.sum()}")

# 截尾处理:将异常值替换为 1% 和 99% 分位数
p1 = df['age'].quantile(0.01)
p99 = df['age'].quantile(0.99)
df['age'] = df['age'].clip(lower=p1, upper=p99)

# ---------- 3. 缺失值填充 ----------
# 收入字段:按用户所在行业的中位数填充
df['income'] = df.groupby('industry')['income'].transform(
    lambda x: x.fillna(x.median())
)

# 逾期天数:缺失表示无逾期,填充为 0
df['overdue_days'] = df['overdue_days'].fillna(0)

# 第三方评分:新增缺失指示变量,并用 -1 填充
df['third_party_score_missing'] = df['third_party_score'].isnull().astype(int)
df['third_party_score'] = df['third_party_score'].fillna(-1)

print("数据清洗完成,当前数据集形状:", df.shape)
关键要点回顾:
  • 数据源选择应遵循“权威优先、行为补充、三方增量”原则。
  • 质量检查四步法(完整性→准确性→一致性→唯一性)必须按顺序执行,缺一不可。
  • 缺失值处理前务必分析缺失机制,非随机缺失时保留缺失指示变量。
  • 异常值处理优先尝试截尾,保留样本量;欺诈类异常建议单独建模。