正如标题所示,我想知道在计算Python / pandas中的协方差矩阵时是否有一种简洁的方法来处理丢失的数据。 考虑数据框
df = pd.DataFrame({'var1': [1,2,3, np.nan, 5, np.nan], 'var2': [1, 1.5, 2, 2.5, np.nan, 3.5]})
如果我们只是做np.cov(df.var1.dropna(), df.var2.dropna())
,我们会收到错误,因为第一列和第二列中有不同数量的缺失值。
我发现的两种解决方法是:
rowind = list(set(df.var1.dropna().index).intersection(set(df.var2.dropna().index)))
和
rowind = (~np.isnan(data.resid1f1)) & (~np.isnan(data.resid1f2))
然后计算np.cov(df.loc[rowind, "var1"], df.loc[rowind, "var2"])
。然而,我想知道是否有一些内置功能可以用一种不那么冗长的方式做到这一点。
答案 0 :(得分:1)
In [110]:
df.dropna().cov()
Out[110]:
var1 var2
var1 1.0 0.50
var2 0.5 0.25
匹配np.cov
:
In [111]:
rowind = (~np.isnan(df.var1)) & (~np.isnan(df.var2))
np.cov(df.loc[rowind, "var1"], df.loc[rowind, "var2"])
Out[111]:
array([[ 1. , 0.5 ],
[ 0.5 , 0.25]])
这与给出不同结果的df.cov
不同,文档声明它排除了缺失的数据,但不清楚它对它们的作用:
In [107]:
df.cov()
Out[107]:
var1 var2
var1 2.916667 0.500
var2 0.500000 0.925
好的,只是弄清楚以上是做什么的:
In [115]:
df.fillna(df.mean(axis=1)).cov()
Out[115]:
var1 var2
var1 2.916667 0.500
var2 0.500000 0.925
答案 1 :(得分:0)
我在下面的要点中重现并举例说明了这种差异,我希望在这次讨论中有用:
# =============================================================================
# NUMPY VS PANDAS: DIFFERENT ESTIMATION OF COVARIANCE IN PRESENCE OF NAN VALUES
# =============================================================================
# data with nan values
M = np.random.randn(10,2)
# add missing values
M[0,0] = np.nan
M[1,1] = np.nan
# Covariance matrix calculations
# ==============================
# numpy
# -----
masked_arr = np.ma.array(M, mask=np.isnan(M))
cov_numpy = np.ma.cov(masked_arr, rowvar=0, allow_masked=True, ddof=1).data
# pandas
# ------
cov_pandas = pd.DataFrame(M).cov(min_periods=0).values
以下显示了计算的示例:
# Homemade covariance coefficient calculation
# (what each of them is actually doing)
# =============================================
# select elements to estimate the element 0,1 in the covariance matrix
x = M[:,0]
y = M[:,1]
mask_x = ~np.isnan(x)
mask_y = ~np.isnan(y)
mask_common = mask_x & mask_y
# numpy
# -----
xn = x-np.mean(x[mask_x])
yn = y-np.mean(y[mask_y])
cov_np = sum(a*b for a,b,c in zip(xn,yn, mask_common) if c)/(np.sum(mask_common)-1)
# pandas
# ------
xn = x-np.mean(x[mask_common])
yn = y-np.mean(y[mask_common])
cov_pd = sum(a*b for a,b,c in zip(xn,yn, mask_common) if c)/(np.sum(mask_common)-1)
请注意,主要区别在于如何对每个变量应用均值函数。
来源:https://gist.github.com/mmngreco/bd86213d9ccd8ddc61683a853ce2fced
编辑:我在pandas中添加了一个问题: