三种常用的相关系数为皮尔逊相关系数斯皮尔曼相关系数Kendall相关系数.Spearman相关系数和Kendall秩相关系数都属于等级相关分析方法Pearson数值的线性关系Spearman排名的单调关系Kendall两两样本的排序一致性皮尔逊相关系数皮尔逊相关(Pearson correlation)系数概述及其计算例_皮尔逊相关系数-CSDN博客皮尔逊相关系数通常用字母r表示衡量两个随机变量之间的线性关系或者说线性关联度一般理解r≈1强正相关r≈−1强负相关r≈0r几乎没有线性关系两个变量之间的协方差和标准差之积的商或者说归一化的协方差具体的公式如果r0表示没有线性关系但是可能是别的关系比如二次曲线只是代表相关但代表因果。import math def pearson_correlation(x, y): 使用 Pearson 公式计算两组数据的线性相关系数。 if len(x) ! len(y): raise ValueError(两组数据的长度必须相同) if len(x) 2: raise ValueError(至少需要两个数据点) mean_x sum(x) / len(x) mean_y sum(y) / len(y) numerator sum( (xi - mean_x) * (yi - mean_y) for xi, yi in zip(x, y)#计算分子 ) sum_square_x sum((xi - mean_x) ** 2 for xi in x)#计算分母 sum_square_y sum((yi - mean_y) ** 2 for yi in y) denominator math.sqrt(sum_square_x * sum_square_y) if denominator 0: raise ValueError(数据没有变化无法计算 Pearson 相关系数) return numerator / denominator def explain_correlation(r): 根据相关系数的绝对值给出一个简单解释。 strength abs(r) if strength 0.8: level 强 elif strength 0.5: level 中等 elif strength 0.3: level 较弱 else: level 很弱或无线性 if r 0: direction 正相关 elif r 0: direction 负相关 else: direction 相关性 return f{level}{direction} def main(): # 示例学习时间与考试成绩 study_hours [1, 2, 3, 4, 5, 6] scores [52, 58, 65, 72, 83, 90] r pearson_correlation(study_hours, scores) print(学习时间, study_hours) print(考试成绩, scores) print(fPearson 相关系数 r {r:.4f}) print(结果解释, explain_correlation(r)) print(注意相关性不等于因果关系。) # SciPy 可以在计算 r 的同时给出显著性检验的 p 值。 try: from scipy.stats import pearsonr scipy_r, p_value pearsonr(study_hours, scores) print(fSciPy 计算结果r {scipy_r:.4f}, p {p_value:.6f}) 代码里的 p 值则用于判断观察到的相关性是否可能只是随机产生的。一般 p 0.05 时认为该相关性具有统计显著性。 两个序列相关系数大于皮尔逊的概率不足p这个相关系数结果的置信度 except ImportError: print(提示运行 pip install scipy 后可同时计算 p 值。) if __name__ __main__: main()正确顺序画散点图→计算Pearson→看正负→看∣r∣大小→看P值斯皮尔曼相关系数斯皮尔曼相关(Spearman correlation)系数概述及其计算例_斯皮尔曼相关系数-CSDN博客用来衡量两个变量之间是否存在单调关系。两者在变大或变小的趋势上多大程度上保持步调一致哪怕没有保持比例关系。Spearman 系数 排名之间的 Pearson 系数全版本的计算公式简易公式d表示第i个数据对的位次值之差n表示总样本数使用排名对异常值不敏感实际计算的时候皮尔逊和斯皮尔曼可以都算。import math def calculate_ranks(values): 把数据转换为秩并列值使用它们所占名次的平均值。 #按数值排序返回索引和值的元组列表 sorted_pairs sorted(enumerate(values), keylambda pair: pair[1]) ranks [0.0] * len(values) i 0 while i len(sorted_pairs): j i while ( #检查后一个数是否与当前数相同 j 1 len(sorted_pairs) and sorted_pairs[j 1][1] sorted_pairs[i][1] ): j 1 # Python 下标从 0 开始但排名从 1 开始所以这里需要加 1。 average_rank ((i 1) (j 1)) / 2 for position in range(i, j 1):#按原始下标把排名放回去 original_index sorted_pairs[position][0] ranks[original_index] average_rank i j 1 return ranks def pearson_correlation(x, y): 计算两组数据的 Pearson 相关系数。 mean_x sum(x) / len(x) mean_y sum(y) / len(y) numerator sum( (xi - mean_x) * (yi - mean_y) for xi, yi in zip(x, y) ) sum_square_x sum((xi - mean_x) ** 2 for xi in x) sum_square_y sum((yi - mean_y) ** 2 for yi in y) denominator math.sqrt(sum_square_x * sum_square_y) if denominator 0: raise ValueError(数据的排名没有变化无法计算 Spearman 相关系数) return numerator / denominator def spearman_correlation(x, y): 先计算两组数据的秩再计算秩之间的 Pearson 相关系数。 if len(x) ! len(y): raise ValueError(两组数据的长度必须相同) if len(x) 2: raise ValueError(至少需要两个数据点) rank_x calculate_ranks(x)#计算秩 rank_y calculate_ranks(y) coefficient pearson_correlation(rank_x, rank_y)#计算秩之间的 Pearson 相关系数 return coefficient, rank_x, rank_y def explain_correlation(r): strength abs(r) if strength 0.8: level 强 elif strength 0.5: level 中等 elif strength 0.3: level 较弱 else: level 很弱或无 if r 0: direction 正相关 elif r 0: direction 负相关 else: direction 单调相关 return f{level}{direction} def main(): # 示例学习时间和成绩中包含并列值。 study_hours [1, 3, 2, 4, 5, 6] scores [50, 65, 60, 80, 85, 95] rho, rank_hours, rank_scores spearman_correlation( study_hours, scores, )#Spearman 系数 排名之间的 Pearson 系数 print(学习时间, study_hours) print(考试成绩, scores) print(学习时间的秩, rank_hours) print(考试成绩的秩, rank_scores) print(fSpearman 相关系数 rho {rho:.4f}) print(结果解释, explain_correlation(rho)) print(注意Spearman 衡量的是单调关系相关性不等于因果关系。) # SciPy 可以同时计算相关系数和显著性检验的 p 值。 try: from scipy.stats import spearmanr scipy_rho, p_value spearmanr(study_hours, scores) print(fSciPy 计算结果rho {scipy_rho:.4f}, p {p_value:.6f}) except ImportError: print(提示运行 pip install scipy 后可同时计算 p 值。) if __name__ __main__: main()Kendall相关系数把样本两两配对看它们的排序方向是否一致。需要两个变量的数据之间应该遵循单调关系monotonic relationship适合小样本和有并列项一致对(Concordant)分歧对1tau-a:假定原始数据中不存在并列排位c一致对d分歧对n样本数量2tau-b:可以处理有相同值的情况c和d则分别代表一致对和分歧对的个数和则分别表示数据X中的并列排位个数和数据Y中的并列排位个数。注意如果是同时发生在X和Y中并列排位则既不计入也不计入。import math def kendall_tau_b(x, y): 手动计算 Kendall tau-b 相关系数支持并列值。 if len(x) ! len(y): raise ValueError(两组数据的长度必须相同) if len(x) 2: raise ValueError(至少需要两个数据点) concordant 0 discordant 0 tied_x 0 tied_y 0 tied_both 0 # 比较所有可能的数据对例如第 0 个与第 1、2、3...个比较。 for i in range(len(x) - 1): for j in range(i 1, len(x)): difference_x x[j] - x[i] difference_y y[j] - y[i] if difference_x 0 and difference_y 0: tied_both 1#两者同时并列这个不计入公式计算 elif difference_x 0: tied_x 1#x有相同的 elif difference_y 0: tied_y 1#y有相同的 elif difference_x * difference_y 0: # 两个变量变化方向相同同序对。 concordant 1 else: # 两个变量变化方向相反逆序对。 discordant 1 denominator math.sqrt( (concordant discordant tied_x) * (concordant discordant tied_y) ) if denominator 0: raise ValueError(数据缺少有效变化无法计算 Kendall 相关系数) tau (concordant - discordant) / denominator details { concordant: concordant, discordant: discordant, tied_x: tied_x, tied_y: tied_y, tied_both: tied_both, } return tau, details def explain_correlation(tau): strength abs(tau) if strength 0.8: level 强 elif strength 0.5: level 中等 elif strength 0.3: level 较弱 else: level 很弱或无 if tau 0: direction 正相关 elif tau 0: direction 负相关 else: direction 相关性 return f{level}{direction} def main(): # 案例学习时间和考试成绩其中学习时间包含并列值。 study_hours [1, 2, 2, 4, 5, 6] scores [50, 65, 60, 80, 85, 95] tau, details kendall_tau_b(study_hours, scores) print(学习时间, study_hours) print(考试成绩, scores) print(同序对数量, details[concordant]) print(逆序对数量, details[discordant]) print(仅学习时间并列的数量, details[tied_x]) print(仅考试成绩并列的数量, details[tied_y]) print(两者同时并列的数量, details[tied_both]) print(fKendall tau-b 相关系数 {tau:.4f}) print(结果解释, explain_correlation(tau)) print(注意相关性不等于因果关系。) # SciPy 验证手动计算结果并给出显著性检验的 p 值。 try: from scipy.stats import kendalltau scipy_tau, p_value kendalltau(study_hours, scores, variantb) print(fSciPy 计算结果tau-b {scipy_tau:.4f}, p {p_value:.6f}) except ImportError: print(提示运行 pip install scipy 后可同时计算 p 值。) if __name__ __main__: main()