4. 数据可视化:特征分布直方图与相关性热图

写代码之前,我建议你先把手停下来,想想自己到底要看到什么。

数据可视化不是为了画好看的图,是为了让你跟数据“对话”。特征分布直方图帮你回答“这个变量长什么样”,相关性热图帮你回答“变量之间有没有猫腻”。这两个图,是我做评分卡模型时必看的第一道关。

4.1 为什么要先看分布?

你想想看,如果某个特征的取值80%都是0,剩下20%集中在100附近,那这个变量基本就是个哑变量。直接扔进逻辑回归,系数会很难看。

我在项目里遇到过一对惨案:一个客户年龄特征,原始数据里居然有350岁的记录。要是没看直方图,模型就学了个“老年人300岁”的奇怪规律。嗯,数据清洗阶段其实就应该处理,但可视化能帮你提前发现这类异常。

避坑提醒:别只用describe()看统计量。均值和标准差会被极端值拉偏,直方图能看到真实的分布形态。我见过一个特征均值是50,标准差200,describe完全正常,但是直方图一画,数据其实是双峰——一个峰在0,一个峰在100,中间全是空挡。

4.2 特征分布直方图,怎么画才有效?

我用Python画直方图,基本就靠matplotlib + seaborn。代码不多,但有几个细节得注意。

import matplotlib.pyplot as plt
import seaborn as sns

# 假设你已经加载了data和特征列表con_features
fig, axes = plt.subplots(4, 5, figsize=(18, 14))
axes = axes.flatten()

for i, col in enumerate(con_features):
    sns.histplot(data[col], bins=50, kde=True, ax=axes[i])
    axes[i].set_title(col, fontsize=10)

# 去掉多余的子图
for j in range(len(con_features), len(axes)):
    fig.delaxes(axes[j])

plt.tight_layout()
plt.show()

这里我故意加了kde=True。核心密度曲线能帮你判断分布是否接近正态——在评分卡里,我们有时候需要对偏态分布做变换,比如对数变换或Box-Cox。你在图上看到长尾巴,心里就有数了。

我的实战习惯:bins设成50左右。太少看不清楚细节,太多会被噪声干扰。另外,对连续变量建议统一用histplot而不是distplot,因为distplot在新版seaborn里已经被弃用了。

4.3 直方图里读什么?

读分布,主要看三点:

  • 偏度:左偏还是右偏?评分卡里,收入、负债这类变量通常右偏,很多客户集中在低区间。
  • 异常尖峰:比如某个年龄刚好40岁的人特别多?检查一下是不是数据录入有默认值。
  • 自然分组:如果出现多峰,可能暗示这个变量在不同客群中有不同模式。我曾经碰到一个“信用卡使用率”变量,双峰分别对应正常用户和套现用户,后来我们直接把它分箱做了WOE编码。

4.4 相关性热图:别让共线性坑了你

直方图看完了,接下来就看变量之间的关系。逻辑回归要求特征之间不能太相关,不然系数会不稳定,解释性也变差。

相关性热图就是一张大表格,用颜色深浅表示相关系数。我现在直接上代码:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 只选连续变量
corr_matrix = data[con_features].corr()

plt.figure(figsize=(14, 12))
sns.heatmap(corr_matrix, 
            annot=True,      # 显示数字
            fmt='.2f',       # 保留两位小数
            cmap='RdBu_r',   # 红蓝配色,红色正相关,蓝色负相关
            center=0,        # 让0值显示为白色
            linewidths=0.5, 
            cbar_kws={'shrink': 0.8})
plt.title('连续变量相关性热图', fontsize=16)
plt.tight_layout()
plt.show()

这里annot=True一定要开。我知道有的人喜欢只看颜色,实际上数字比颜色更精确。比如0.89和0.91,颜色差异不大,但前者可能还能接受,后者基本可以判定存在共线性。

我的经验阈值:绝对值超过0.8的相关系数,我会打上红色标记。超过0.9的基本上两个变量只能留一个。记得有一次,模型里同时放了“年收入”和“月收入”,相关系数0.98,逻辑回归的系数直接爆炸到几万。去掉一个后,模型立马稳定。

4.5 热图不止看共线性

很多人觉得热图就是检查共线性的,其实你还能看出:

  • 与目标变量的关系:把目标变量(比如好坏标签)也放到相关性矩阵里。如果某个特征与目标的相关性绝对值小于0.05,那这个特征基本贡献不了信息,可以考虑淘汰。
  • 变量分组:几个特征彼此高度正相关,可能属于同一维度(比如“房贷金额”和“房产价值”)。这时候可以做因子分析或者直接选一个代表。
  • 非线性关系线索:如果两个变量相关系数接近0,但业务上明显有关系(比如年龄和违约率呈U型),说明不是线性关系。热图看不出来,需要靠后面的WOE分析或者分箱。
相关性系数常用解读标准
相关系数范围相关强度对评分卡的影响
|r| ≥ 0.9极强必须删除其一,否则共线性严重
0.7 ≤ |r| < 0.9强建议检查业务含义,考虑合并
0.5 ≤ |r| < 0.7中等一般可接受,但需要观察VIF
|r| < 0.5弱或不相关通常没问题
一个小技巧:如果特征数量太多(比如超过30个),热图会密密麻麻看不清。我习惯先用单变量筛选把特征压缩到20个以内,然后再画热图。否则一个图里塞满几百个格子,跟马赛克一样,反而看不出结构。

4.6 整个可视化流程,我习惯这样走

下面这张流程图总结了我在信用评分卡项目里做特征可视化时的标准步骤:

特征可视化分析流程 特征可视化分析流程图 原始数据加载 特征分布直方图 检查偏度、异常尖峰 相关性热图 判断共线性 & 变量关系 特征保留 / 删除 / 变换 要点 • 先看分布形状 • 再看共线性 • 最后决定保留/删除 • 必要时做变换

从原始数据到最终决策,只有两步可视化,但每一步都能帮你避免很多坑。

4.7 几个你可能会踩的坑

讲完了流程,再分享几个我在真实项目里遇到的教训:

  • 只看热图,不看散点图:相关系数0.5,可能是线性关系,也可能是非线性但相关性被平均掉了。我建议你在热图基础上,挑几个相关系数在0.4~0.6之间的变量对,画个散点图看看。有一次,两个变量相关系数0.62,散点图显示完全是“U型”,其实它们是互补关系。
  • 忘记处理缺失值再画图:pandas的corr()默认会忽略NaN,但如果缺失比例高,相关性会被稀释。你先看看缺失情况,如果超过30%,建议先做缺失处理再画热图。
  • 把分类变量直接丢进相关性热图:性别、婚姻状况这类变量,不能直接计算皮尔逊相关系数。要么做标签编码后看Spearman,要么单独做列联表分析。我一般在热图里只放连续变量,分类型变量单独用卡方检验。
严重警告:不要在热图里一次性塞进100个变量。不仅图难看,而且你会被密密麻麻的数字搞晕。建议先用IV值或方差筛选,保留30个以内,再画热图。我曾经带过一个新人,他把全部200个特征画了一张热图,结果图里根本看不到任何规律,白白浪费半天时间。

好,直方图和热图看完,你对每个特征的长相和变量之间的关系就有了全局感。接下来就可以进入特征工程的正餐了——分箱、WOE编码、IV筛选。不过那是下一站的事儿,先把今天这两张图练扎实了再往前走。