如何计算 Pearson 相关矩阵并仅保留有效值?

How can I compute the Pearson correlation matrix and retain only significant values?

我有一个 4×3 矩阵,X,并希望形成 3×3 皮尔逊相关矩阵,C,通过计算所有 3 个可能列之间的相关性获得X 的组合。但是,C 中与不具有统计显着性的相关性相对应的条目应设置为零。

我知道如何使用 scipy.stats 中的 pearsonr 获得成对相关性和显着性值。例如,

import numpy as np
from scipy.stats.stats import pearsonr

X = np.array([[1, 1, -2], [0, 0, 0], [0, .2, 1], [5, 3, 4]])
pearsonr(X[:, 0], X[:, 1])

returns (0.9915008164289165, 0.00849918357108348)X 的第一列和第二列之间的相关性约为 .9915,p 值为 .0085。

我可以使用嵌套循环轻松获得我想要的矩阵:

  1. C 预填充为 3×3 零矩阵。
  2. 嵌套循环的每一遍将对应X的两列。与这对列对应的 C 条目将设置为成对相关,前提是 p 值小于或等于我的阈值,比如 .01。

我想知道是否有更简单的方法。我知道在 Pandas 中,我可以在基本上一行中创建相关矩阵 C

import pandas as pd

df = pd.DataFrame(data=X)
C_frame = df.corr(method='pearson') 
C = C_frame.to_numpy()

有没有办法在没有循环的情况下获取 p 值的矩阵或数据框 P?如果是这样,如果 P 中相应的 p 值超过我的阈值,我如何将 C 的每个条目设置为零?

查看 pearsonr 的文档会发现用于计算相关性的公式。使用矢量化获得矩阵每一列之间的相关性应该不会太难。

虽然您可以使用 pandas 计算 C 的值,但我将展示整个过程的纯 numpyan 实现。

首先,计算 r 值:

X = np.array([[1,  1, -2],
              [0,  0,  0],
              [0, .2,  1],
              [5,  3,  4]])
n = X.shape[0]

X -= X.mean(axis=0)
s = (X**2).sum(axis=0)
r = (X[..., None] * X[..., None, :]).sum(axis=0) / np.sqrt(s[:, None] * s[None, :])

考虑到 scipy 中存在 beta 分布,计算 p 值变得简单。直接取自文档:

dist = scipy.stats.beta(n/2 - 1, n/2 - 1, loc=-1, scale=2)
p = 2 * dist.cdf(-abs(r))

您可以根据您的阈值从 p 简单地制作一个掩码,并将其应用于 r 以制作 C:

mask = (p <= 0.01)
C = np.zeros_like(r)
C[mask] = r[mask]

更好的选择可能是就地修改 r

r[p > 0.1] = 0

函数形式:

def non_trivial_correlation(X, threshold=0.1):
    n = X.shape[0]
    X = X - X.mean(axis=0) # Don't modify the original
    x = (X**2).sum(axis=0)
    r = (X[..., None] * X[..., None, :]).sum(axis=0) / np.sqrt(s[:, None] * s[None, :])
    p = 2 * scipy.stats.beta(n/2 - 1, n/2 - 1, loc=-1, scale=2).cdf(-abs(r))
    r[p > threshold] = 0
    return r