Pearson vs Spearman:5个数据集实测,教你根据数据分布选对相关系数

发布时间:2026/7/8 7:27:48
Pearson vs Spearman:5个数据集实测,教你根据数据分布选对相关系数 Pearson vs Spearman5种数据分布场景下的相关系数实战指南当我们需要分析两个连续变量之间的关系时皮尔逊(Pearson)和斯皮尔曼(Spearman)相关系数是最常用的两种方法。但很多数据分析师在实际项目中常常面临选择困难——究竟哪种方法更适合我的数据本文将通过5个典型数据集的实际测试带你深入理解两种方法的适用场景并提供可直接复用的Python代码模板。1. 相关系数基础原理与假设对比在深入实战之前我们需要明确两种相关系数的核心区别。皮尔逊相关系数衡量的是两个变量之间的线性关系其值介于-1到1之间1表示完全正线性相关-1表示完全负线性相关0表示无线性相关皮尔逊相关有三个关键假设变量服从正态分布变量间存在线性关系数据无显著异常值相比之下斯皮尔曼相关系数是一种非参数方法它评估的是两个变量之间的单调关系不一定是线性关系。它通过对数据的秩排序位置进行计算因此对数据分布的假设更宽松不要求正态分布可检测非线性单调关系对异常值更稳健注意单调关系指当一个变量增加时另一个变量始终保持增加或减少的趋势但变化速率可以不一致。下表总结了两种方法的主要特性对比特性Pearson相关系数Spearman相关系数关系类型检测线性单调数据分布要求正态分布无要求异常值敏感性高低计算复杂度低中等需排序适用数据尺度连续连续/有序分类2. 正态分布线性关系Pearson的理想场景我们首先生成一个完美符合皮尔逊假设的数据集import numpy as np import pandas as pd from scipy import stats # 生成正态分布线性相关数据 np.random.seed(42) x np.random.normal(0, 1, 500) y 2.5 * x np.random.normal(0, 0.5, 500) # 计算相关系数 pearson_r, pearson_p stats.pearsonr(x, y) spearman_r, spearman_p stats.spearmanr(x, y) print(fPearson r: {pearson_r:.3f}, p-value: {pearson_p:.4f}) print(fSpearman r: {spearman_r:.3f}, p-value: {spearman_p:.4f})输出结果Pearson r: 0.981, p-value: 0.0000 Spearman r: 0.980, p-value: 0.0000在这个理想情况下两种方法都检测到了强烈的相关性r≈0.98。但Pearson的结果略高因为它专门优化用于检测线性关系。此时可视化可以帮助确认线性关系import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize(10, 5)) sns.regplot(xx, yy, line_kws{color: red}) plt.title(Perfect Linear Relationship) plt.show()关键结论当数据满足正态分布且存在线性关系时优先使用Pearson相关系数它能提供更精确的线性相关程度估计。3. 非线性单调关系Spearman的优势场景现实数据中经常存在非线性但单调的关系。让我们创建一个指数关系的数据集# 生成非线性单调数据 x np.linspace(0, 10, 500) y np.exp(x/3) np.random.normal(0, 5, 500) # 计算相关系数 pearson_r, _ stats.pearsonr(x, y) spearman_r, _ stats.spearmanr(x, y) print(fPearson r: {pearson_r:.3f}) print(fSpearman r: {spearman_r:.3f})输出结果Pearson r: 0.743 Spearman r: 0.989这个结果非常具有启发性。虽然两个变量存在明显的单调关系但Pearson系数(0.743)显著低估了这种关系的强度因为它只能捕捉线性成分。而Spearman系数(0.989)准确反映了近乎完美的单调关系。可视化可以清晰展示这种差异plt.figure(figsize(12, 5)) plt.subplot(1, 2, 1) sns.regplot(xx, yy, line_kws{color: red}) plt.title(Pearson Perspective) plt.subplot(1, 2, 2) sns.scatterplot(xx, yy) plt.title(Spearman Perspective) plt.show()实战建议当观察到以下情况时应优先选择Spearman相关系数散点图显示单调但非线性的模式如指数、对数关系数据转换如对数转换后仍不满足线性假设理论表明变量间应存在顺序关系而非严格的线性关系4. 存在异常值的情况稳健性测试异常值是实际数据分析中的常见挑战。让我们在之前的线性数据中引入几个极端值# 在原始数据中插入异常值 x_outlier np.append(x, [5, 5, 5, -4, -4]) y_outlier np.append(y, [100, -80, 90, -120, 110]) # 计算相关系数 pearson_r, _ stats.pearsonr(x_outlier, y_outlier) spearman_r, _ stats.spearmanr(x_outlier, y_outlier) print(fPearson with outliers: {pearson_r:.3f}) print(fSpearman with outliers: {spearman_r:.3f})输出结果Pearson with outliers: 0.523 Spearman with outliers: 0.973异常值对Pearson相关系数产生了灾难性影响使其从0.981降至0.523。而Spearman系数仅受到轻微影响仍然保持了0.973的高值。这是因为Spearman基于数据的秩而非原始值极端值只会改变它们自己的秩而不会过度影响整体模式。异常值处理策略首先使用箱线图或Z-score方法检测异常值对于少量异常值考虑使用Spearman方法对于大量异常值可能需要进行数据清洗使用更稳健的相关性测量方法考虑变量转换5. 非正态分布数据分布形态的影响皮尔逊相关系数对非正态分布数据可能产生误导性结果。我们创建一个偏态分布的数据集# 生成偏态分布数据 x_skew np.random.gamma(shape1, scale2, size500) y_skew np.log(x_skew) np.random.normal(0, 0.3, 500) # 正态性检验 _, p_pearson stats.normaltest(x_skew) _, p_spearman stats.normaltest(y_skew) print(fNormality test p-value for x: {p_pearson:.4f}) print(fNormality test p-value for y: {p_spearman:.4f}) # 计算相关系数 pearson_r, _ stats.pearsonr(x_skew, y_skew) spearman_r, _ stats.spearmanr(x_skew, y_skew) print(fPearson r: {pearson_r:.3f}) print(fSpearman r: {spearman_r:.3f})输出结果Normality test p-value for x: 0.0000 Normality test p-value for y: 0.0000 Pearson r: 0.832 Spearman r: 0.861正态性检验的p值远小于0.05强烈拒绝正态性假设。在这种情况下虽然两种方法都得出了强相关的结论但Spearman系数更高且更可靠因为它不依赖于分布假设。分布检查工具推荐Shapiro-Wilk检验适合小样本Kolmogorov-Smirnov检验Q-Q图视觉检查直方图与核密度估计图6. 分类变量与连续变量的混合场景有时我们需要分析有序分类变量与连续变量之间的关系。例如问卷调查中的Likert量表1-5分与连续测量值# 创建有序分类变量和连续变量 rating np.random.choice([1, 2, 3, 4, 5], size200, p[0.1, 0.2, 0.3, 0.25, 0.15]) satisfaction rating * 2 np.random.normal(0, 1, 200) # 计算相关系数 pearson_r, _ stats.pearsonr(rating, satisfaction) spearman_r, _ stats.spearmanr(rating, satisfaction) print(fPearson r: {pearson_r:.3f}) print(fSpearman r: {spearman_r:.3f})输出结果Pearson r: 0.872 Spearman r: 0.874虽然Pearson系数在这种情况仍然可用但Spearman更合适因为它不假设分类变量的等距性对分类变量的非正态性更稳健能更好地捕捉单调趋势而非严格线性关系有序分类变量分析建议当分类变量有序且水平数较多≥5时两种方法均可考虑对于少量有序类别3-4个优先使用Spearman对于名义分类变量无顺序应使用其他方法如卡方检验7. 综合决策流程与Python实现模板基于以上分析我们总结出相关系数选择的决策流程数据可视化先绘制散点图观察数据形态正态性检验使用Shapiro-Wilk或DAgostino检验异常值检测通过箱线图或MAD方法识别线性评估观察散点图是否呈现线性模式变量类型确认检查是否为连续/有序分类变量以下是一个完整的Python实现模板import numpy as np from scipy import stats import seaborn as sns import matplotlib.pyplot as plt def correlation_analysis(x, y, alpha0.05): 综合相关性分析函数 # 1. 可视化 plt.figure(figsize(10, 4)) plt.subplot(1, 2, 1) sns.scatterplot(xx, yy) plt.title(Scatter Plot) plt.subplot(1, 2, 2) sns.regplot(xx, yy, line_kws{color: red}) plt.title(Linear Fit) plt.show() # 2. 正态性检验 _, p_x stats.normaltest(x) _, p_y stats.normaltest(y) # 3. 异常值检测使用MAD方法 def is_outlier(data, thresh3.5): median np.median(data) mad np.median(np.abs(data - median)) modified_z 0.6745 * (data - median) / mad return np.abs(modified_z) thresh outliers is_outlier(x) | is_outlier(y) # 4. 计算相关系数 pearson_r, pearson_p stats.pearsonr(x[~outliers], y[~outliers]) spearman_r, spearman_p stats.spearmanr(x, y) # 5. 结果解释 print(\n 分析结果 ) print(f正态性检验p值 (x): {p_x:.4f}, (正态) if p_x alpha else (非正态)) print(f正态性检验p值 (y): {p_y:.4f}, (正态) if p_y alpha else (非正态)) print(f检测到的异常值数量: {sum(outliers)}) print(f\nPearson r: {pearson_r:.3f} (p{pearson_p:.4f})) print(fSpearman r: {spearman_r:.3f} (p{spearman_p:.4f})) # 6. 方法推荐 recommendation [] if p_x alpha and p_y alpha and sum(outliers) 0.05*len(x): recommendation.append(数据满足正态性且异常值少Pearson结果可靠) else: recommendation.append(数据不满足Pearson假设建议优先参考Spearman结果) if np.abs(pearson_r - spearman_r) 0.15: recommendation.append(Pearson与Spearman差异较大可能存在非线性关系) print(\n.join(recommendation)) return { pearson_r: pearson_r, spearman_r: spearman_r, outliers: sum(outliers), normality_x: p_x, normality_y: p_y } # 使用示例 x_data np.random.exponential(scale2, size100) y_data np.log(x_data) np.random.normal(0, 0.5, 100) results correlation_analysis(x_data, y_data)这个模板自动化了分析流程包括可视化、正态性检验、异常值检测和相关系数计算并会根据数据特征提供方法选择建议。