如何计算 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。
我可以使用嵌套循环轻松获得我想要的矩阵:
- 将
C
预填充为 3×3 零矩阵。
- 嵌套循环的每一遍将对应
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
我有一个 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。
我可以使用嵌套循环轻松获得我想要的矩阵:
- 将
C
预填充为 3×3 零矩阵。 - 嵌套循环的每一遍将对应
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