Numpy中如何计算含NaN值数据集的加权协方差矩阵
带缺失值场景下支持aweights参数的加权协方差计算方案
不需要修改numpy源码,两种轻量方案即可实现需求:
方案1:成对剔除缺失值后调用原生np.cov
该方案和np.ma.cov默认的成对删除缺失值逻辑完全一致,兼容性最好:
- 先遍历所有待计算协方差的变量对,筛除两个变量中任意一方存在
NaN的样本,同步保留有效样本对应的权重值 - 将筛选后无缺失的样本子集、匹配好的权重数组直接传入
np.cov,正常传入aweights参数计算即可 - 该方案不会引入额外计算偏差,适合绝大多数使用场景
最小实现代码如下:
import numpy as np def nan_weighted_cov(x, aweights, **cov_kwargs): # 入参维度默认对齐np.cov规范:第一维度为变量,第二维度为样本 n_vars, n_samples = x.shape cov_mat = np.zeros((n_vars, n_vars), dtype=np.float64) for i in range(n_vars): for j in range(i, n_vars): # 标记两个变量均无缺失的有效样本 valid_flag = ~np.isnan(x[i]) & ~np.isnan(x[j]) pair_data = np.vstack([x[i][valid_flag], x[j][valid_flag]]) pair_w = aweights[valid_flag] pair_cov = np.cov(pair_data, aweights=pair_w, **cov_kwargs) cov_mat[i, j] = pair_cov[0, 1] if i != j else pair_cov[0, 0] cov_mat[j, i] = cov_mat[i, j] return cov_mat
方案2:缺失位置权重置零快速计算
如果数据集维度较低、缺失值占比小,可以用更简洁的无循环实现:
- 先将所有
NaN值临时替换为0,同时把存在缺失值的样本对应的aweights权重置为0 - 加权协方差计算时,权重为0的样本不会对结果产生任何贡献,等价于自动忽略缺失值
- 注意提前备份原始权重数组,避免修改原始数据影响后续计算
示例代码:
import numpy as np # x为原始输入数据集,w为原始aweights数组 x_filled = np.nan_to_num(x, nan=0.0) w_edited = w.copy() # 若样本排布为列(和np.cov默认维度一致),任意变量存在NaN则对应样本权重置0 w_edited[np.isnan(x).any(axis=0)] = 0 cov_result = np.cov(x_filled, aweights=w_edited)
提示:如果你的输入数据集是样本按行、变量按列排布,需要将上述代码中
np.isnan(x).any(axis=0)的axis=0改为axis=1,同时在调用np.cov时传入rowvar=False参数对齐维度。
内容的提问来源于stack exchange,提问作者Frank Liu
相关产品推荐
相关产品推荐

