2、数据获取与初步探索

这一章咱们来动手拿数据。我用的是 Kaggle 上的 Give Me Some Credit 数据集,英文全称是 "Give Me Some Credit, We Can Pay You Back?"。说白了,它就是信用评分领域的经典入门数据,包含 15 万条贷款申请人记录,目标变量是 SeriousDlqin2yrs——表示借款人在 2 年内是否发生过严重逾期。

2.1 下载与加载

去 Kaggle 官网搜 "Give Me Some Credit",下载 cs-training.csv(训练集)和 cs-test.csv(测试集)。我个人习惯把数据放在项目目录的 data/ 文件夹下,这样后面路径管理方便。

import pandas as pd

train = pd.read_csv('data/cs-training.csv')
test = pd.read_csv('data/cs-test.csv')
print('训练集形状:', train.shape)
print('测试集形状:', test.shape)

跑出来训练集 (150000, 12),测试集 (101503, 12)。嗯,12 列包括:Unnamed: 0(索引,可删)、目标变量 SeriousDlqin2yrs,以及 10 个特征。

一个小坑:你下载回来的 csv 第一列是行号索引,不是有效特征。我建议一上来就把它删掉:train.drop('Unnamed: 0', axis=1, inplace=True),否则后面计算特征相关性时会多出一个无意义列。

2.2 数据类型与基本统计

先看列的类型分布:

train.info()

我截一部分输出给大家看:

列名Non-Null CountDtype
SeriousDlqin2yrs150000int64
RevolvingUtilizationOfUnsecuredLines150000float64
age150000int64
NumberOfTime30-59DaysPastDueNotWorse150000int64
DebtRatio150000float64
MonthlyIncome120269float64
NumberOfOpenCreditLinesAndLoans150000int64
NumberOfTimes90DaysLate150000int64
NumberRealEstateLoansOrLines150000int64
NumberOfTime60-89DaysPastDueNotWorse150000int64
NumberOfDependents146409float64

注意到 MonthlyIncome 有 27731 个缺失,NumberOfDependents 有 3591 个缺失。为什么会出现缺失?我在项目里遇到最多的情况是申请人没填收入,或者系统录入时漏掉了。缺失值处理咱们后面专门讲,这里先留个印象。

2.3 初步分布探索

看一看目标变量 SeriousDlqin2yrs 的分布:

train['SeriousDlqin2yrs'].value_counts(normalize=True)

输出大概是:

  • 0(未逾期):93.3%
  • 1(严重逾期):6.7%

典型的类别不平衡问题。我记得上次做风控模型时,正样本只有 5%,如果直接训练,模型会倾向于全部预测为 0,准确率高但毫无意义。所以后面特征工程和采样都要格外小心。

再看几个连续特征的统计:

train.describe()

挑几个关键列说说:

特征均值标准差最小值25%50%75%最大值
RevolvingUtilizationOfUnsecuredLines6.05249.760.00.030.150.5650708.0
age52.3014.770415263109
DebtRatio353.002037.000.00.180.370.87329664.0
MonthlyIncome6470.0014782.000.03400540082003008750.0
NumberOfOpenCreditLinesAndLoans8.455.150581158

RevolvingUtilizationOfUnsecuredLines 最大值 50708.0,明显是异常值——按理说这个比率应该在 0~1 之间。为什么会这样?可能是数据录入错误,或者用户信息被篡改。这就是我们做特征工程要处理的脏数据。还有 age 最小值为 0,明显不合理,应该是缺失值被错误填充了。

我常用的快速检查法:画直方图和箱线图,一眼就能看出离群点。比如 train.hist(bins=50, figsize=(12,10)),你会看到几个长尾特别重的变量。

2.4 探索流程总览

我把整个初步探索的流程画成一张图,方便大家对照着走:

数据初步探索流程 1. 读取 CSV 2. info() / describe() 3. 缺失值分析 4. 分布统计 & 直方图 5. 异常值检测 6. 汇总统计 & 可视化

这张图就是我做初步探索的标准工作流。先读数据,接着看基本统计,然后重点关注缺失值和异常值。图里我把「缺失值分析」作为核心分叉点——往左做分布统计,往右做异常值检测,最后汇总。当然,实际项目里你可能会来回迭代,但整体逻辑不变。

2.5 两个容易踩的坑

我曾经在项目里栽过两次跟头:
第一次,直接用 train.describe() 里的均值填充缺失值,结果模型在收入特征上完全失效——因为收入分布是右偏的,均值被高收入样本拉高,导致低收入群体被错误归为“正常”。
第二次,没注意到 NumberOfTime30-59DaysPastDueNotWorse 这个特征的名字,以为是“30-59天逾期次数”,实际它的含义是“从未超过60天的好记录”,理解反了,导致特征工程方向全错。
记住:看列名时一定要读 Kaggle 的变量说明,别凭感觉。

好了,到此我们完成了数据获取和初步探索。掌握了数据的基本样貌——类型、缺失、分布、异常点——下一步才能有针对性地做特征清洗和构造。我个人喜欢把这一步叫做“对数据做一次完整的体检”,体检报告越详细,后面的手术就越精准。