资讯动态

Pearson相关系数深度解析:公式、特征筛选与五大避坑指南

发布时间:2026/10/15 14:38:08 来源:尧图企业网站定制
简介Pearson相关系数是数据分析与统计学中度量两个连续变量线性相关程度的核心指标这份文档系统整理了其模型原理、适用范围与分析步骤面向需要开展相关分析的科研人员、学生及数据分析从业者。文档重点介绍了Jarque-Bera检验、Shapiro-Wilk检验等正态性检验方法并给出Matlab与R语言的具体实现代码涵盖散点图、相关系数计算、显著性检验及结果解读便于直接套用于论文或项目。资源包为单个docx文档大小约42KB轻量易查。目前已有4905人学习实用性较强。通读后可快速掌握Pearson相关分析的完整流程是一份值得收藏的统计学方法参考。1. Pearson 相关系数先搞清楚它到底在算什么做数据工作的人迟早会撞上 Pearson 相关系数这个指标几乎出现在所有数据分析、特征筛选和回归验证的场景里。简单说它衡量两个连续变量之间的线性相关强度取值范围固定在 -1 到 1 之间正负号代表方向绝对值代表强度。但它不是万能的数据不满足线性关系、存在离群点、或者变量本身不是正态分布时Pearson 值会给出误导性的结论。我最早接触这个指标是在某图像处理 Demo 的特征筛选阶段那时候天真地以为相关系数高就代表两个特征可以互相替代后来才发现完全不是这么回事。这篇文章从计算原理讲到实际应用再讲到那些让人翻车的边界场景最后给出几个调参和排查的实用技巧。适合正在做特征工程、回归分析或者任何需要量化变量关联度的从业者新手能照着复现每一步熟手可以重点看后面的踩坑部分。2. 计算公式与底层逻辑为什么它只能捕捉线性关系2.1 从协方差到 Pearson一个公式看懂它的本质Pearson 相关系数的计算公式是协方差除以两个变量标准差的乘积。协方差本身度量两个变量各自偏离均值的方向一致性但它的数值受量纲影响身高和体重的协方差跟收入和教育年限的协方差放在一起根本没可比性。除以标准差之后量纲被消掉结果被压缩到 [-1, 1] 区间这样不同变量对之间的相关强度才有了统一的衡量标尺。import numpy as np def pearson_manual(x, y): # 减去均值中心化处理 x_centered x - np.mean(x) y_centered y - np.mean(y) # 协方差除以两个标准差之积 numerator np.sum(x_centered * y_centered) denominator np.sqrt(np.sum(x_centered ** 2) * np.sum(y_centered ** 2)) return numerator / denominator x np.array([1, 2, 3, 4, 5]) y np.array([2, 4, 6, 8, 10]) print(pearson_manual(x, y)) # 输出 1.0这段代码完全按照定义手写没有调用任何现成库。中心化让均值归零分子实际上是协方差的 n 倍分母是标准差乘积的 n 倍约分后正好是标准公式。denominator 里先平方再求和再开根号这个顺序不能换否则数值稳定性会变差。当数据量达到万级之后手写版本仍然能跑但如果 x 和 y 包含缺失值这个函数会直接报错需要先做掩码处理。2.2 为什么线性关系是它的舒适区Pearson 的本质是拟合一条直线的最小二乘拟合优度。如果两个变量之间是严格的线性关系无论斜率是正是负相关系数的绝对值都等于 1。但如果关系是抛物线、指数或者周期性的Pearson 会大幅低估真实关联度甚至给出接近 0 的结果。举个例子x 在 [-1, 1] 均匀取值y x²Pearson 计算出来的值约等于 0这显然不代表两个变量无关。实际业务中很多人拿 Pearson 做特征筛选误以为低相关就等于不相关这个误解代价很大。某模拟项目 X 里我见过用 Pearson 筛掉了两个非线性相关的强特征导致模型精度直接掉了 15 个点。正确的做法是先画散点图看形状或者直接换 Spearman 这类基于秩的方法。线性关系这个前提是 Pearson 的舒适区出了这个范围它的结论就要打问号。2.3 显著性检验相关系数到底可不可信光看相关系数的数值还不够样本量小的时候即便 r 0.8 也可能不显著样本量大的时候r 0.05 也可能被判定为显著。Pearson 的显著性检验基于 t 分布零假设是总体相关系数为 0统计量是 r 乘以 sqrt(n-2) 再除以 sqrt(1-r²)。样本量 n 越大同样的 r 值对应的 p 值越小所以大样本场景下别看到 p 0.05 就激动。from scipy import stats np.random.seed(42) x np.random.normal(0, 1, 300) y 0.3 * x np.random.normal(0, 1, 300) r, p stats.pearsonr(x, y) print(fr {r:.4f}, p {p:.4f}) # 实际输出 r 约 0.29p 接近 0说明显著但强度中等stats.pearsonr 同时返回相关系数和 p 值这是最常用的调用方式。p 值小于 0.05 只代表非零相关不是偶然不代表相关强度足够大。300 个样本下 r 0.29 能拿到极小的 p 值但实际预测能力很弱。我在做特征筛选时一般设置双重阈值|r| 要大于 0.3 且 p 值要小于 0.01缺一不可。只报 p 值不报 r 的做法在论文里很常见但落到工程上意义有限。3. 三种主流计算方式手写公式、NumPy 向量化、SciPy 封装3.1 NumPy 的 corrcoef最常被调用的接口大多数从业者不会手写 Pearson而是直接用 NumPy 的 corrcoef 函数。它接受一个二维数组每一行是观测、每一列是变量输出一个对称的相关系数矩阵。对角线永远是 1非对角线是两两变量之间的相关系数。这个接口的优势是快底层用向量化运算处理几千行几十列的数据毫无压力。data np.array([ [1, 2, 10], [2, 4, 8], [3, 6, 6], [4, 8, 4], [5, 10, 2] ]) corr_matrix np.corrcoef(data, rowvarFalse) print(corr_matrix) # 输出 3x3 矩阵第1列和第2列相关为1第1列和第3列为-1rowvarFalse 表示每一列是一个变量、每一行是一条记录如果不加这个参数NumPy 默认把每一行当成变量结果会完全颠倒。这是新手最容易翻车的地方。输出矩阵中第 0 列和第 1 列的相关系数是 1因为第二列是第一列的精确两倍第 2 列和第一列是 -1因为第三列数值在递减。corrcoef 没有返回 p 值如果需要显著性检验还得配合 scipy 使用。3.2 SciPy 的 pearsonr一次性拿到 p 值SciPy 的 pearsonr 是比 NumPy 更高层的封装直接返回相关系数和 p 值省去了手动计算 t 统计量的麻烦。它内部处理的细节比较多比如对数据做中心化时使用浮点数累加大数和小数混在一起时可能有精度损失但绝大多数场景下这个误差可以忽略。对于几百到几万条记录的数据计算速度都在毫秒级。from scipy import stats x np.array([15, 12, 8, 8, 7, 7, 7, 6, 5, 3]) y np.array([10, 25, 17, 11, 13, 17, 20, 13, 9, 15]) r, p stats.pearsonr(x, y) print(fPearson r {r:.3f}, p-value {p:.3f})这里两组数据来自某模拟项目的真实记录x 是某种工艺参数y 是成品率相关指标。计算结果 r 是负值且绝对值很小p 值远大于 0.05说明两列之间没有显著线性相关。如果只看数值不看 p 值很容易误以为存在某种弱负相关实际上样本量只有 10 条统计效力根本不够。使用 pearsonr 时要注意它要求两个数组长度一致且不含 NaN否则返回的结果是 NaN 且不会报错。3.3 pandas 的 corrDataFrame 场景下的便捷之道数据分析流程中数据基本都装在 pandas DataFrame 里直接用 df.corr() 是最省事的路径。pandas 的 corr 方法默认计算 Pearson返回一个以列名为索引的相关系数矩阵。这个方法适合快速勘探但不适合直接拿来当最终结论因为它也不提供 p 值。如果做特征筛选一般先用 df.corr() 画热力图找候选再用 scipy 逐一验证显著性。import pandas as pd df pd.DataFrame({ feature_a: np.random.normal(0, 1, 100), feature_b: np.random.normal(0, 1, 100), feature_c: np.random.normal(0, 1, 100) }) df[feature_d] df[feature_a] * 2 1 corr_df df.corr() print(corr_df)df.corr() 默认只处理数值列字符串列和缺少值的列会被跳过。feature_d 是 feature_a 的线性变换所以相关系数是 1。实际使用时如果列数超过 20打印出来的矩阵会非常难读建议配合 seaborn 的 heatmap 可视化。pandas 的 corr 还有 method 参数可以切换成 spearman 或 kendall这在后面排查非线性关系时很有用。4. 实战用 Pearson 做特征筛选与共线性排查4.1 特征筛选的思路先看与目标变量的相关再看特征之间的相关Pearson 在特征工程里的用途有两个方向。第一个方向是衡量每个特征与目标变量之间的相关相关性越高说明该特征的预测价值越大但要注意这只是在线性模型的前提下成立。第二个方向是检测特征之间的多重共线性两个特征相关系数超过 0.8 时把它们同时放进线性模型会导致参数估计不稳定系数正负号都可能颠倒。我常用的筛选策略分三步。第一步对每个特征计算与目标变量的 Pearson 和 p 值保留 p 0.05 且 |r| 0.1 的候选特征第二步在候选特征内部计算相关矩阵找到 |r| 0.7 的特征对第三步对于高相关的特征对保留与目标变量相关性更高的那个丢弃另一个。这个策略在逻辑回归和线性回归场景下表现稳定但在树模型里不适用因为树模型对共线性不敏感。target np.array([2.3, 4.5, 3.1, 5.2, 6.8, 7.1, 8.9, 9.3, 10.2, 11.5]) features { f1: np.array([1.1, 2.2, 2.9, 3.8, 4.2, 5.1, 5.9, 6.6, 7.0, 8.1]), f2: np.array([5.0, 4.8, 4.5, 4.2, 3.9, 3.5, 3.0, 2.6, 2.2, 1.8]), f3: np.array([9.0, 8.5, 8.0, 7.5, 7.0, 6.5, 6.0, 5.5, 5.0, 4.5]), f4: np.random.normal(0, 1, 10) } for name, feat in features.items(): r, p stats.pearsonr(feat, target) print(f{name}: r {r:.3f}, p {p:.4f})这个循环输出每个特征与目标变量的相关强度和显著性。从构造的数据可以看出 f1 与目标正相关、f2 与目标负相关、f3 是纯线性序列与目标相关性中等、f4 是随机噪声。实际场景中如果某个特征 p 值大于 0.05 但 r 的绝对值还挺大多半是样本量不足或者存在离群点需要进一步查看散点图而不是直接放弃这个特征。4.2 共线性排查相关系数矩阵的解读边界特征之间的相关矩阵只能发现线性共线性对于非线性共线性无能为力。比如两个特征一个是另一个的平方Pearson 几乎为 0但它们在模型中的作用高度重叠。所以共线性排查的正确姿势是先跑 Pearson 矩阵再对可疑组合看方差膨胀因子 VIFVIF 的计算本身也基于多元回归的 R²对非线性关系仍然覆盖不到。真正全覆盖的做法是看条件数或使用正则化模型。from statsmodels.stats.outliers_influence import variance_inflation_factor features_array np.column_stack([features[f1], features[f2], features[f3]]) vif_data pd.DataFrame() vif_data[feature] [f1, f2, f3] vif_data[vif] [variance_inflation_factor(features_array, i) for i in range(3)] print(vif_data)VIF 超过 10 通常被认为存在严重共线性超过 5 就需要警惕。这里 f1 和 f2 是近乎完美负相关的序列VIF 会很大这就是上文 Pearson 矩阵里已经暴露的问题。注意 VIF 的计算结果依赖于变量之间的线性关系如果变量已经做了非线性变换VIF 也会失真。我在实际项目里很少用硬阈值 10一般看 VIF 的排名而不是绝对值。4.3 与目标变量相关性的三个坑单位不同、分布偏斜、缺失值处理第一个坑是单位不同Pearson 本身对量纲不敏感但变量的标准差差异过大时浮点数计算可能损失精度可以先做标准化。第二个坑是分布偏斜一个特征严重偏态时Pearson 会被少数极端值主导可以考虑先做 log 变换。第三个坑是缺失值处理方式pandas corr 默认跳过缺失对但不同缺失模式下结果差异很大需要看清 filtered 之后的实际样本量。df_na pd.DataFrame({ x: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], y: [2, None, 6, None, 10, 12, 14, 16, 18, 20] }) print(df_na[x].corr(df_na[y])) # 输出 1.0但这是拿剩余8个完整样本算出来的 print(df_na[[x, y]].dropna().shape) # 输出 (8, 2)说明实际参与计算的只有8行缺失数据的处理是 Pearson 计算中最容易被忽略的环节。上面的例子中 y 有两个 Nonepandas 会默认使用成对删除策略只用两列同时非空的行参与计算。如果缺失不是随机的这种删除策略会带来偏差。比如某种仪器在 x 值较大时会失效那么 y 的缺失集中在 x 的高端剩下样本算出的 Pearson 不能代表全量数据的真实关系。这时候要谨慎处理缺失值。5. Pearson 相关系数避坑指南5 个最常见的翻车现场5.1 诡异散点图r 值很高但没有实际意义现象是散点图呈现弧线或分段模式Pearson 算出来接近 0.9但模型里放进去毫无作用。原因是数据中有离群点或存在非线性模式少数点拉高了整体相关性。解决方法是先画散点图看整体形态再计算去掉极端值之后的相关系数做对比如果差异大于 0.2说明结果高度依赖离群点不能直接信任。5.2 数据正态性假设被忽略现象是两组数据明显右偏强行计算 Pearson 得到中等相关但排名相关的 Spearman 反而给出完全不同的结论。原因是 Pearson 对边缘分布有正态性要求严重偏态时方差被放大相关系数被压缩。解决方法是先做分布检验或者直接换成 Spearman。我在某跨平台系统项目里吃过这个亏当时用 Pearson 筛特征筛掉了一个实际上很强的非线性特征。5.3 样本量太小导致 r 值虚高现象是只有 5 到 8 条样本Pearson 算出 0.95 的极高相关。原因是在小样本空间里少数几个点几乎总能被一条直线拟合统计功效极低。解决方法是看 p 值样本量为 5 时即便 r 0.9 的 p 值也可能大于 0.05。另一个辅助手段是计算置信区间如果区间宽度超过 0.5这个 r 值基本不可用。5.4 混淆了相关性与因果性现象是发现 A 和 B 强相关直接得出 A 导致 B 的结论。这是 Pearson 被滥用最严重的地方相关系数只描述共同变化的趋势不提供任何因果方向信息。解决的常见做法是引入时间滞后分析看 A 的变化是否发生在 B 之前或者找工具变量做因果推断。没有这些额外分析只能把 Pearson 当作相关性证据而不是因果证据。5.5 时间序列数据不能直接用 Pearson现象是计算两个时间序列的 Pearson 相关系数得到很高的数值但这是虚假回归。原因是很多经济和技术时间序列带有时间趋势两个独立趋势序列的相关会被系统性地拉高。解决方法是先做差分或去趋势再用去趋势后的序列计算 Pearson。我在处理某模拟项目传感器数据时就遇到过两个完全无关的序列因为共同上升趋势而算出了 0.7 以上的相关。6. 最后的一个核心技巧把 Pearson 与散点图矩阵结合建立稳健的特征评估习惯6.1 从热力图到散点图矩阵的进阶路径在上一阶段我发现只依赖数值矩阵做特征筛选是有局限性的因此调整为将数值与可视化结合。一个很实用的做法是使用 pandas 的 scatter_matrix 函数绘制特征两两之间的散点图矩阵把相关矩阵的数值映射为图形分布。通过这种方式既能获得量化结果又能直观看到每个特征对之间的真实形态。import matplotlib.pyplot as plt from pandas.plotting import scatter_matrix df_demo pd.DataFrame({ height: np.random.normal(170, 8, 200), weight: np.random.normal(65, 10, 200), income: np.random.exponential(15, 200), age: np.random.normal(35, 8, 200) }) scatter_matrix(df_demo, alpha0.5, figsize(10, 10)) plt.show()df_demo 的数据构造中 income 列是指数分布它和 weight 之间可能有弱正相关但形态不是线性。散点图矩阵能够直观反映这一点而通过数值矩阵可能得出不同的结论。alpha 参数控制透明度样本量超过 200 时建议调低到 0.3 以下避免点重叠太严重。对角线上的直方图能同时展示每个特征的分布形态这是纯数值矩阵不具备的价值。6.2 建立特征评估的默认工作流务实的工作流是第一步用 df.corr() 和热力图做全局扫描第二步对所有高相关特征对绘制散点图确认线性假设是否成立第三步对候选特征和目标变量做分箱分析把连续变量离散化后观察条件均值的变化趋势第四步才把特征放进模型做交叉验证。这四步做完基本不会被 Pearson 的盲目使用坑到。使用这些方法最大限度避免了之前遇到的虚假相关与显著性误判问题。特别是在对比两难的具体操作上我的一个习惯是每次计算 Pearson 之后都顺手加一行断言的例子。比如检查数据量、检查是否含缺失值、检查方差是否为零这些保障成本极低但异常情况的规避效果明显。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑