如何用Scipy向量化计算二维数组与一维参考数组的Spearman相关系数
实现向量化计算Spearman相关系数
你遇到的问题是因为直接调用spearmanr(M, reference)时,函数会计算所有输入变量(M的100个列 + 参考向量)之间的两两相关,所以得到101×101的结果矩阵。下面提供两种向量化实现方式:
方法一:利用Spearman相关的定义(高效向量化)
Spearman相关系数本质是变量秩变换后的皮尔逊相关系数,我们可以手动完成秩计算,再通过向量化的皮尔逊相关计算得到结果:
from scipy.stats import rankdata import numpy as np rng = np.random.default_rng() M = rng.standard_normal((37, 100)) reference = rng.standard_normal((37, 1)) # 对M的每一列(样本)和参考向量计算秩(沿0轴,即每个样本内部排序) M_ranked = rankdata(M, axis=0) ref_ranked = rankdata(reference, axis=0) # 中心化数据(皮尔逊相关需要消除均值影响) M_centered = M_ranked - M_ranked.mean(axis=0) ref_centered = ref_ranked - ref_ranked.mean() # 计算协方差与标准差的比值,得到皮尔逊相关(即Spearman相关) covariance = np.dot(M_centered.T, ref_centered) / M.shape[0] m_std = M_centered.std(axis=0, ddof=0)[:, np.newaxis] ref_std = ref_centered.std(ddof=0) result = covariance / (m_std * ref_std) print(result.shape) # 输出 (100, 1)
方法二:从全量相关矩阵中提取目标结果(代码简洁)
如果不想手动实现秩变换,可以合并参考向量与M,调用spearmanr后提取参考向量与每个样本的相关系数:
from scipy.stats import spearmanr import numpy as np rng = np.random.default_rng() M = rng.standard_normal((37, 100)) reference = rng.standard_normal((37, 1)) # 将参考向量与M合并为一个矩阵,参考向量作为第一列 combined = np.hstack([reference, M]) # 计算所有变量间的Spearman相关 res = spearmanr(combined, axis=0) # 提取第一行(参考向量)与后面100列(M的样本)的相关系数,调整形状为(100,1) result = res.statistic[0, 1:].reshape(-1, 1) print(result.shape) # 输出 (100, 1)
两种方法都能得到你需要的(100,1)结果,其中方法一避免了计算不必要的样本间相关,效率更高;方法二代码更简洁,适合快速实现。
内容的提问来源于stack exchange,提问作者QuanticDisaster
相关产品推荐
相关产品推荐

