¿Cómo obtener eficientemente la matriz de correlación (con valores p) de un marco de datos con valores de NaN?

Estoy tratando de calcular una matriz de correlación y filtrar las correlaciones basadas en los valores p para descubrir los pares altamente correlacionados.

Para explicar lo que quiero decir, digamos que tengo un marco de datos como este.

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

Para el coeficiente de correlación. Usé pd.corr (). Este método puede procesar el marco de datos con valores de NaN y, lo que es más importante, tolera pares de columnas que tienen superposición 0 (col A y col B):

rho = df.corr()

       A          B            C           D
A   1.000000     NaN       -0.609994    0.041204
B   NaN          1.0       -0.500000    -1.000000
C   -0.609994    -0.5       1.000000    0.988871
D   0.041204     -1.0       0.988871    1.000000

El desafío es calcular el valor p. No encontré un método incorporado para hacer esto. Sin embargo decorrelación de columnas pandas con significación estadística, @BKay proporcionó una forma de bucle para calcular el valor p. Este método presentará un error si hay menos de 3 superposiciones, por lo que modifiqué agregando una excepción de error.

ValueError: matriz de tamaño cero para la operación de reducción máxima que no tiene identidad

pval = rho.copy()
for i in range(df.shape[1]): # rows are the number of rows in the matrix.
    for j in range(df.shape[1]):
        try:
            df_ols = pd.ols(y=df.iloc[:,i], x=df.iloc[:,j], intercept=True)
            pval.iloc[i,j]  = df_ols.f_stat['p-value']
        except ValueError:
            pval.iloc[i,j]  = None

pval
        A        B            C           D
A   0.000000    NaN         0.582343    0.973761
B   NaN         0.000000    0.666667    NaN
C   0.582343    0.666667    0.000000    0.011129
D   0.973761    NaN         0.011129    0.000000

Este método genera una matriz de valor p, pero se vuelve extremadamente lenta cuando aumenta el tamaño del marco de datos original (mi marco de datos real es ~ 5000 filas x 500 columnas). ¿Qué sugeriría hacer para obtener esta matriz de valor p de manera eficiente para un marco de datos de gran tamaño?

Respuestas a la pregunta(0)

Su respuesta a la pregunta