3. 数据准备:风控数据集字段说明、缺失值处理、异常值检测与处理

在构建坏账率预警模型之前,数据准备是决定模型上限的关键步骤。本节将围绕风控数据集的核心字段、缺失值处理策略以及异常值检测方法展开,确保后续特征工程与模型训练建立在干净、可靠的数据基础之上。

3.1 风控数据集字段说明

典型的风控数据集通常包含三类信息:用户基础属性、信用历史行为以及借贷交易记录。下表列出了建模过程中最常用的字段及其业务含义:

字段名称 数据类型 业务含义 示例值
user_id string 用户唯一标识 U10002345
loan_amount float 借款金额(元) 5000.00
loan_term int 借款期限(月) 12
interest_rate float 年化利率(%) 8.5
age int 借款人年龄 32
income float 月收入(元) 12000.00
credit_score int 外部征信评分(300-850) 680
overdue_days_hist int 历史最大逾期天数 15
loan_count_6m int 近6个月借款次数 3
is_default int 标签:是否坏账(0/1) 0
字段选择建议:优先保留与违约行为强相关的字段,如 credit_score、overdue_days_hist、loan_count_6m。对于缺失率超过 70% 的字段,建议直接剔除,避免引入噪声。

3.2 缺失值处理策略

风控数据中缺失值普遍存在,处理不当会导致模型偏差或信息损失。常见的缺失值处理方式包括删除、填充与模型预测。下图展示了缺失值处理的决策流程:

缺失值处理决策流程 检测缺失值 缺失率 < 5% ? 直接删除缺失行 是 缺失率 5%-30% ? 否 统计量填充 是 模型预测填充 否 适用场景 缺失率低,样本充足 适用场景 缺失率 > 30%,信息重要

在实际操作中,不同字段的缺失值处理方式有所区别。下表总结了常见字段的推荐填充策略:

字段 缺失率范围 推荐处理方式 说明
income 10%-20% 中位数填充 收入分布右偏,中位数更稳健
credit_score 5%-15% 均值填充或模型预测 征信评分与违约强相关,优先模型预测
age < 5% 直接删除缺失行 缺失率低,删除影响小
overdue_days_hist 20%-30% 填充为 0 缺失通常表示无逾期历史
关键原则:缺失值处理应保持业务可解释性。例如,overdue_days_hist 缺失时填充为 0 比填充均值更符合业务逻辑。

3.3 异常值检测与处理

异常值会严重干扰 LightGBM 的分裂点选择,导致模型过拟合或泛化能力下降。常用的异常值检测方法包括 IQR 四分位距法和 Z-Score 方法。下图对比了两种方法的检测逻辑:

异常值检测方法对比 IQR 四分位距法 Q1 - 1.5×IQR Q3 + 1.5×IQR IQR = Q3 - Q1 适用于:非正态分布数据 Z-Score 方法 Z = (x - μ) / σ |Z| > 3 视为异常 阈值可调:2.5 / 3.0 / 3.5 适用于:近似正态分布数据 异常值处理方式 截尾(Winsorize) | 删除 | 替换为边界值 实践建议 风控数据中,贷款金额、收入等字段常呈长尾分布,优先使用 IQR 方法;信用评分等近似正态字段可使用 Z-Score。

以下代码展示了使用 Python 对风控数据集进行异常值检测与截尾处理的典型实现:

import pandas as pd
import numpy as np

def detect_and_cap_outliers(df, columns, method='iqr', threshold=1.5):
    """
    对指定列进行异常值检测并截尾处理
    :param df: DataFrame
    :param columns: 待处理列名列表
    :param method: 'iqr' 或 'zscore'
    :param threshold: IQR 倍数或 Z-Score 阈值
    :return: 处理后的 DataFrame
    """
    df_clean = df.copy()
    for col in columns:
        if method == 'iqr':
            Q1 = df_clean[col].quantile(0.25)
            Q3 = df_clean[col].quantile(0.75)
            IQR = Q3 - Q1
            lower_bound = Q1 - threshold * IQR
            upper_bound = Q3 + threshold * IQR
        elif method == 'zscore':
            mean = df_clean[col].mean()
            std = df_clean[col].std()
            lower_bound = mean - threshold * std
            upper_bound = mean + threshold * std
        else:
            raise ValueError("method 必须为 'iqr' 或 'zscore'")
        # 截尾处理
        df_clean[col] = df_clean[col].clip(lower=lower_bound, upper=upper_bound)
    return df_clean

# 示例:对贷款金额和收入进行 IQR 截尾
df_processed = detect_and_cap_outliers(
    df, 
    columns=['loan_amount', 'income'], 
    method='iqr', 
    threshold=1.5
)
print("异常值处理完成,数据形状:", df_processed.shape)
注意:异常值处理不应一刀切。对于风控场景中的 overdue_days_hist 字段,极端值(如逾期 180 天)本身包含重要风险信号,建议保留或单独编码,而非直接截尾。

3.4 数据准备总结清单

完成本节操作后,建议对照以下清单确认数据准备阶段的质量:

  • 字段完整性:确认所有建模字段已加载,无遗漏关键特征。
  • 缺失值处理:每列缺失率已评估,并采用合适的填充或删除策略。
  • 异常值处理:对连续型字段执行 IQR 或 Z-Score 检测,并完成截尾或删除。
  • 数据类型校验:确保数值字段为 float 或 int,类别字段为 category 或 object。
  • 标签分布检查:确认 is_default 列中正负样本比例,为后续采样或权重调整做准备。