直接调用scipy.stats.pearsonr计算皮尔逊相关系数最轻量可控,返回(r_value, p_value)元组,需手动处理缺失值和一维输入,注意异常值与非线性关系的局限性。

怎么用 scipy.stats.pearsonr 算两个变量的相关系数
直接调 pearsonr 是最轻量、最可控的方式,适合你只关心一对变量、或需要拿到 p 值做显著性判断的场景。它不处理缺失值,也不接受 DataFrame 列名自动推导,得自己传 array 或 Series。
常见错误是传入含 NaN 的数组,结果直接报 ValueError: Input arrays must not contain NaNs;或者传了二维数组(比如误把整个 DataFrame 传进去),报 Too many dimensions。
- 先用
.dropna()对齐两列:df[['x', 'y']].dropna(),再拆成x_clean和y_clean -
pearsonr返回元组:(r_value, p_value),别只取第一个 - 如果数据量小(
n ),会报错;<code>n == 3是最低可用门槛 - 它默认不做任何标准化,输入必须是数值型;传字符串或 category 会抛
TypeError
为什么 df.corr(method='pearson') 结果和手算不一致
多数时候不是算法问题,而是数据预处理不一致。Pandas 的 corr 默认使用 pairwise complete observations:对每一对列,独立地删掉该两列都为 NaN 的行,而不是全局删行。
这会导致不同变量对之间的样本量 n 不同,r 值和 p 值就不可比。如果你后续要画热力图,又希望所有格子基于同一份干净数据,就得提前统一清洗。
立即学习“Python免费学习笔记(深入)”;
- 想强制统一基准:先
df_clean = df.dropna(),再df_clean.corr() - 默认行为下,某列全为
NaN会被静默排除(不报错,但结果里没它) -
method='pearson'是默认值,可以省略;但显式写上更防误读 - 结果是
DataFrame,索引和列名来自原df,注意列名是否含空格或特殊字符——可能造成后续 seaborn 绘图 KeyError
Seaborn 热力图里 annot=True 数字重叠、看不清怎么办
这是典型尺寸与内容不匹配的问题。seaborn.heatmap 不会自动缩放字体或调整格子大小,全靠你控制 figsize、annot_kws 和 xticklabels/yticklabels。
最常踩的坑是:直接拿原始宽高画 20×20 的相关矩阵,结果数字糊成一片,连正负号都分不清。
- 先用
plt.figure(figsize=(len(df.columns)//2 + 2, len(df.columns)//2 + 2))粗估尺寸(列数多就放大) -
annot_kws={'size': max(6, 10 - len(df.columns)//3)}动态调字体,避免硬编码 - 加
square=True让格子变方,视觉更稳;否则长宽比失衡会让数字挤歪 - 如果变量名太长,用
xticklabels=[x[:8]+'…' if len(x)>8 else x for x in df.columns]截断,不然标签堆叠
相关系数接近 ±1 却画不出明显颜色深浅,是不是代码错了
不是代码错,是 heatmap 默认用线性 colormap,而你的数据集中在两端(比如一堆 0.92–0.98),中间没值,导致色阶拉不开。人眼对微小差异不敏感,纯靠颜色深浅很难分辨 0.95 和 0.97。
另一个可能是你用了 vmin/vmax 错误设成了 (-1, 1),但实际数据范围只有 (0.8, 0.99),等于把全部信息压缩在色条最顶端一小段里。
- 显式设置色阶范围:
vmin=0.7, vmax=1.0,让有效区间占满色条 - 换更敏感的 colormap,比如
cmap='RdBu_r'比默认'viridis'对 ± 方向更友好 - 加
center=0强制以 0 为中心,能突出正负方向差异(尤其当你混着正负强相关时) - 别依赖颜色判读精度——真要比较 0.95 和 0.97,还是得看
annot=True显示的数字本身
皮尔逊相关本质是线性度量,非线性关系再强它也接近 0;另外它对异常值极度敏感,单个离群点就能把 r 值从 0.3 拉到 0.8。做热力图前,最好先扫一眼散点图矩阵,或用 df.plot.scatter 快速验证几对关键变量——别让数字带着你跑偏。










