3. 数据探索:加载信贷数据集、查看数据分布、处理缺失值与异常值

数据探索是评分卡建模的基石。在构建 LightGBM 评分卡之前,必须对原始信贷数据进行全面探查,理解字段含义、统计分布、缺失情况与异常特征。本节将带领你完成从数据加载到清洗的全流程,确保后续建模输入质量可靠。

3.1 加载信贷数据集

我们使用公开的信贷违约数据集(如 Home Credit Default Risk 或 Give Me Some Credit),通过 Pandas 加载并初步观察结构。

import pandas as pd
import numpy as np

# 加载训练集与测试集
train = pd.read_csv('credit_train.csv')
test = pd.read_csv('credit_test.csv')

print(f"训练集形状: {train.shape}")
print(f"测试集形状: {test.shape}")
print("\n训练集前5行:")
print(train.head())

加载后,首先检查字段名称、数据类型与内存占用,为后续探索做准备。

字段名 类型 非空数 示例值
id int64 100000 1, 2, 3
age float64 99850 45.0, 32.0
income float64 99500 50000.0, 32000.0
loan_amount float64 100000 15000.0, 8000.0
default int64 100000 0, 1

3.2 查看数据分布

对连续型变量使用描述性统计与直方图,对分类型变量使用频次统计,快速掌握数据整体形态。

# 连续变量统计
print(train[['age', 'income', 'loan_amount']].describe())

# 目标变量分布
print(train['default'].value_counts(normalize=True))
关键观察: 信贷数据通常存在严重的类别不平衡(违约样本占比 5%~10%),后续建模需考虑采样或权重调整。

分布检查的核心指标包括:均值、标准差、最小值、最大值、四分位数。重点关注变量是否服从业务常识(如年龄不应为负,收入不应为 0)。

信贷数据集分布概览 年龄分布 均值 42.3,标准差 12.1 收入分布 均值 5.2万,右偏严重 贷款金额分布 均值 1.2万,多峰分布 目标变量 default 0: 92% | 1: 8% 分布检查要点 1. 连续变量需检查极端值、缺失比例、偏度与峰度 2. 分类变量需检查类别频次、罕见类别与业务合理性

3.3 处理缺失值

缺失值是信贷数据中的常见问题。首先统计各字段缺失比例,然后根据业务含义与缺失机制选择处理策略。

# 缺失值统计
missing_ratio = train.isnull().mean().sort_values(ascending=False)
print(missing_ratio[missing_ratio > 0])
字段 缺失比例 处理策略
employment_length 12.5% 中位数填充
income 5.0% 按行业均值填充
age 1.5% 中位数填充
house_ownership 0.8% 众数填充
缺失值处理原则: 缺失比例低于 5% 的字段可直接删除或简单填充;高于 20% 的字段需评估是否保留;介于之间的字段建议使用模型预测填充或分箱为“缺失”类别。
# 中位数填充连续变量
train['age'].fillna(train['age'].median(), inplace=True)
train['income'].fillna(train['income'].median(), inplace=True)

# 众数填充分类变量
train['house_ownership'].fillna(train['house_ownership'].mode()[0], inplace=True)

3.4 处理异常值

异常值会严重影响评分卡的稳定性与区分能力。通过箱线图与业务规则识别异常,并采取截尾或转换处理。

异常值检测与处理流程 箱线图检测 业务规则检测 Z-Score 检测 截尾处理(Winsorize) 对数/Box-Cox 转换 清洗后数据集
# 箱线图法:定义异常值边界
def cap_outliers(series, lower_quantile=0.01, upper_quantile=0.99):
    lower = series.quantile(lower_quantile)
    upper = series.quantile(upper_quantile)
    return series.clip(lower, upper)

train['income'] = cap_outliers(train['income'])
train['loan_amount'] = cap_outliers(train['loan_amount'])

# 业务规则:年龄应在 18~100 之间
train = train[(train['age'] >= 18) & (train['age'] <= 100)]
异常值处理注意事项: 不要盲目删除异常值,需结合业务判断。例如,高收入客户可能是优质客群,直接删除会损失信息。建议先标记异常,在建模时作为单独特征输入。

3.5 数据探索总结

完成缺失值与异常值处理后,需再次检查数据质量,确保无遗漏问题。

检查项 处理前 处理后
缺失字段数 4 0
异常值字段数 3 0
样本量 100000 99850
违约率 8.0% 8.0%

清洗后的数据集可直接用于特征工程与 LightGBM 建模。下一阶段将进行特征分箱与 WOE 编码,为评分卡转换做准备。