如何有效地获取具有 NaN 值的数据帧的相关矩阵(具有 p 值)?
How to efficiently get the correlation matrix (with p-values) of a data frame with NaN values?
我正在尝试计算相关矩阵,并根据 p 值过滤相关以找出高度相关的对。
为了解释我的意思,假设我有一个这样的数据框。
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
为相关系数。我使用了 pd.corr()。此方法可以处理具有 NaN 值的数据帧,更重要的是,它容忍具有 0 重叠的列对(col A 和 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
挑战在于计算 p 值。我没有找到执行此操作的内置方法。然而,从 pandas columns correlation with statistical significance 开始,@BKay 提供了一种计算 p 值的循环方法。如果少于3个,这个方法会报错overlaps.So我做了一些修改,添加了错误异常。
ValueError: zero-size array to reduction operation maximum which has no identity
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
此方法输出一个 p 值矩阵,但当原始数据框的大小增加时它会变得非常慢(我的真实数据框是 ~ 5000 行 x 500 列)。您建议如何有效地为大型数据框获取此 p 值矩阵。
这个问题原来是一个很好的解决方案。
看起来 Pandas 不再支持 OLS,所以我通过一个略微修改的版本进行了管道传输,应该会给出相同的结果:
# Use this package for OLS
import statsmodels.formula.api as sm
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:
y = df.columns[i]
x = df.columns[j]
df_ols = sm.ols(formula = 'Q("{}") ~ Q("{}")'.format(y,x), data = df).fit()
pval.iloc[i,j] = df_ols.pvalues[1]
except ValueError:
pval.iloc[i,j] = None
pval
sns.heatmap(pval,
center = 0,
cmap="Blues",
annot = True)
plt.show()
我正在尝试计算相关矩阵,并根据 p 值过滤相关以找出高度相关的对。
为了解释我的意思,假设我有一个这样的数据框。
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
为相关系数。我使用了 pd.corr()。此方法可以处理具有 NaN 值的数据帧,更重要的是,它容忍具有 0 重叠的列对(col A 和 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
挑战在于计算 p 值。我没有找到执行此操作的内置方法。然而,从 pandas columns correlation with statistical significance 开始,@BKay 提供了一种计算 p 值的循环方法。如果少于3个,这个方法会报错overlaps.So我做了一些修改,添加了错误异常。
ValueError: zero-size array to reduction operation maximum which has no identity
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
此方法输出一个 p 值矩阵,但当原始数据框的大小增加时它会变得非常慢(我的真实数据框是 ~ 5000 行 x 500 列)。您建议如何有效地为大型数据框获取此 p 值矩阵。
这个问题原来是一个很好的解决方案。
看起来 Pandas 不再支持 OLS,所以我通过一个略微修改的版本进行了管道传输,应该会给出相同的结果:
# Use this package for OLS
import statsmodels.formula.api as sm
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:
y = df.columns[i]
x = df.columns[j]
df_ols = sm.ols(formula = 'Q("{}") ~ Q("{}")'.format(y,x), data = df).fit()
pval.iloc[i,j] = df_ols.pvalues[1]
except ValueError:
pval.iloc[i,j] = None
pval
sns.heatmap(pval,
center = 0,
cmap="Blues",
annot = True)
plt.show()