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

时间:2019-12-19 20:15:25

标签: python pandas numpy matrix pearson-correlation

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

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

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])

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

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

  1. C预先填充为3乘3的零矩阵。
  2. 嵌套循环的每次通过将对应于X的两列。如果p值小于或等于我的阈值(例如.01),则与这对列对应的C条目将设置为成对相关。

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

import pandas as pd

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

有没有一种方法可以获取没有循环的p值P的矩阵或数据帧?如果是这样,应该如何将C中的相应p值超过我的阈值,将P的每个条目设置为零?

1 个答案:

答案 0 :(得分:2)

仔细阅读pearsonr的文档,可以发现用于计算相关性的公式。使用矢量化获取矩阵各列之间的相关性应该不太困难。

虽然您可以使用熊猫计算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