我找不到一个函数,当数据中有NaN时,计算包含多于两个变量的观测值的数组的相关系数矩阵。有一些函数可以为变量对执行此操作(或者只使用~is.nan()屏蔽数组)。但是通过循环遍历大量变量来使用这些函数,计算每对变量的相关性可能非常耗时。
所以我自己尝试并很快意识到这样做的复杂性是协方差正确归一化的问题。我对你如何做的意见非常感兴趣。
以下是代码:
def nancorr(X,nanfact=False):
X = X - np.nanmean(X,axis=1,keepdims = True)*np.ones((1,X.shape[1]))
if nanfact:
mask = np.isnan(X).astype(int)
fact = X.shape[1] - np.dot(mask,mask.T) - 1
X[np.isnan(X)] = 0
if nanfact:
cov = np.dot(X,X.T)/fact
else:
cov = np.dot(X,X.T)
d = np.diag(cov)
return cov/np.sqrt(np.multiply.outer(d,d))
该函数假定每行都是变量。它基本上是来自numpy的corrcoeff()的调整代码。 我相信有三种方法可以做到这一点:
(1)对于每对变量,只采用那些一个和另一个变量都不是NaN的观察结果。如果你想同时对多个对进行计算并且上面的代码中没有涉及,那么这可以说是最准确但也是最难编程的。然而,为什么抛弃每个变量的均值和方差的信息,只是因为另一个变量的相应条目是NaN?因此,另外两个选择。
(2)我们用nanmean贬低每个变量,每个变量的方差是它的纳方差。对于协方差,每个观察,其中一个或另一个变量是NaN,但不是两者,是对无协变的观察,因此设置为零。协方差的因子是1 /(观察的数量,其中两个变量都不是NaN-1),用n表示。相关系数的分母中的两个方差都由它们相应的非NaN观测数减去1来计算,分别由n1和n2表示。这是通过在上面的函数中设置nanfact = True来实现的。
(3)可能希望协方差和方差具有与没有NaN的相关系数的情况相同的因子。在这里执行此操作的唯一有意义的方法(如果选项(1)不可行),则简单地忽略(1 / n)/ sqrt(1 / n1 * n2)。由于该数字小于1,估计的相关系数将比(2)中的(绝对值)更大,但将保持在-1,1之间。这是通过设置nanfact = False来实现的。
我对你对方法(2)和(3)的看法非常感兴趣,特别是,我非常希望在不使用循环的情况下看到(1)的解决方案。
答案 0 :(得分:8)
我认为您正在寻找的方法是来自pandas的corr()
。例如,数据帧如下。您也可以参考这个问题。 How to efficiently get the correlation matrix (with p-values) of a data frame with NaN values?
import pandas as pd
df = pd.DataFrame({'A': [2, None, 1, -4, None, None, 3],
'B': [None, 1, None, None, 1, 3, None],
'C': [2, 1, None, 2, 2.1, 1, 0],
'D': [-2, 1.1, 3.2, 2, None, 1, None]})
df
A B C D 0 2 NaN 2 -2 1 NaN 1 1 1.1 2 1 NaN NaN 3.2 3 -4 NaN 2 2 4 NaN 1 2.1 NaN 5 NaN 3 1 1 6 3 NaN 0 NaN
rho = df.corr()
rho
A B C D A 1.000000 NaN -0.609994 -0.441784 B NaN 1.0 -0.500000 -1.000000 C -0.609994 -0.5 1.000000 -0.347928 D 0.041204 -1.0 -0.347928 1.000000