我找不到能为数据中存在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而不是两者均是NaN的每个观察值都是无协变量的观察值,因此将其设置为零。则协方差的因子为1 /(观察数,其中两个变量都不都是NaN-1),用n表示。相关系数的分母中的两个方差均由其对应的非NaN观测值减去1分别表示,分别由n1和n2表示。这可以通过在上面的函数中设置nanfact = True来实现。

(3)可能希望协方差和方差具有与没有NaNs的相关系数相同的因子。在这里执行此操作的唯一有意义的方法(如果选项(1)不可行)是简单地忽略(1 / n)/ sqrt(1 / n1 * n2)。由于此数字小于1,因此估计的相关系数(在绝对值上)将比(2)中的大,但将保持在-1,1之间。这可以通过设置nanfact = False来实现。

我会对您对方法(2)和(3)的意见非常感兴趣,尤其是,我非常希望看到不使用循环的(1)解决方案。

我认为您正在寻找的方法是pandas中的corr()。 例如,如下所示的数据框。 您也可以参考此问题。 如何有效地获取具有NaN值的数据帧的相关矩阵(具有p值)?

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

因此,熊猫显然提供了我在上述选项(1)下描述的内容。 也就是说,在计算成对相关性时,它仅使用在两个相应列中均不是Nan的观察值-甚至用于计算均值和方差。 我上面没有提到的另一个问题是,我不确定这是否保证半正定Cov。 顺便说一句,您似乎为示例数据框提供了错误的corr矩阵。 例如。 C,D条目应显示为-0.347928。

更正了corr-matrix结果。

对于带有nans的数组,panda.corr的速度很慢。 它基本上是一个手写的python循环。