第一章:数据探索性分析(EDA)基础
做风控模型这么多年,我有个习惯——拿到数据后,绝不急着建模。先做EDA,就像医生看病前先做检查一样。你想想看,数据质量都不过关,模型再花哨也是白搭。
这一章,咱们就聊聊EDA中最基础、也最核心的几个环节。说白了,就是先摸清数据的脾气。
1.1 描述性统计:先给数据画个像
描述性统计,就是给数据做个「体检报告」。我一般会先看这几个指标:均值、中位数、标准差。
- 均值:数据的平均水平。但要注意,均值容易被极端值带偏。
- 中位数:数据的中间位置。比均值更稳健,能反映真实水平。
- 标准差:数据波动的大小。标准差越大,数据越分散。
举个例子,某小微企业样本的「年营收」数据:
| 指标 | 值(万元) |
|---|---|
| 均值 | 185.6 |
| 中位数 | 92.3 |
| 标准差 | 312.4 |
看到没?均值185.6,中位数才92.3。差距这么大,说明数据右偏严重——少数大企业把均值拉高了。我在项目中遇到过类似情况,如果只看均值,你会误以为大部分企业营收都不错,其实一半以上连100万都不到。
1.2 缺失值分布与可视化
缺失值,是风控建模的老大难。我见过太多人一上来就删掉缺失行,结果模型效果一塌糊涂。
正确的做法是:先搞清楚缺失值长什么样。
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据
df = pd.read_csv('enterprise_data.csv')
# 查看缺失值数量
missing_count = df.isnull().sum()
print(missing_count)
# 可视化缺失值
plt.figure(figsize=(10, 6))
missing_count.plot(kind='bar')
plt.title('各字段缺失值数量')
plt.ylabel('缺失数量')
plt.show()
嗯,这里要注意:缺失值不是越多越糟糕。我曾经处理过一个「纳税等级」字段,缺失率高达60%。按理说该删掉,但后来发现——缺失的企业大多是刚成立的小微企业,本身就没纳税记录。这个缺失本身就是一个特征!
1. 缺失是随机的,还是有规律的?
2. 缺失比例是否超过50%?
3. 缺失本身是否包含业务含义?
1.3 异常值初步识别
异常值,就是数据里的「刺头」。它们可能是录入错误,也可能是真实的极端情况。
我常用的方法是箱线图法。箱线图会告诉你:哪些数据点超出了1.5倍四分位距。
import seaborn as sns
# 绘制箱线图
plt.figure(figsize=(12, 4))
sns.boxplot(x=df['负债率'])
plt.title('负债率箱线图')
plt.show()
为什么会这样?有些企业的负债率超过200%,明显不合理。我记得有一次,一个企业的负债率显示为850%,后来一查,是数据录入时把「85%」写成了「850%」。这种错误,不画箱线图根本发现不了。
1.4 单变量分布分析
单变量分布,说白了就是看每个字段自己的「长相」。我一般用两种图:直方图和箱线图。
直方图:看数据的形状
# 绘制直方图
plt.figure(figsize=(10, 4))
plt.hist(df['年营收'], bins=50, edgecolor='black')
plt.title('年营收分布直方图')
plt.xlabel('年营收(万元)')
plt.ylabel('频数')
plt.show()
直方图能告诉你数据是正态分布、偏态分布还是双峰分布。比如「年营收」通常是右偏的——大部分企业营收不高,少数头部企业拉高了整体。
箱线图:看数据的离散程度
箱线图除了能看异常值,还能看数据的集中趋势和离散程度。我习惯把多个字段的箱线图放在一起对比:
# 多字段箱线图对比
plt.figure(figsize=(14, 6))
sns.boxplot(data=df[['年营收', '负债率', '利润率']])
plt.title('关键指标箱线图对比')
plt.show()
你想想看,如果「利润率」的箱线图特别扁,说明大部分企业利润都差不多。如果特别宽,说明企业间差异很大。这些信息,对后续特征工程和模型选择都很有帮助。