对带有屏蔽元素的 numpy ndarray 取平均值

Taking mean of numpy ndarray with masked elements

我有一个从实验中获取的值的 MxN 数组。其中一些值无效,并设置为 0 以表示无效。我可以使用

构造一个 valid/invalid 值的掩码
mask = (mat1 == 0) & (mat2 == 0)

产生一个 MxN 的布尔数组。应该注意的是,被屏蔽的位置并没有整齐地跟随矩阵的列或行 - 因此简单地裁剪矩阵不是一种选择。

现在,我想沿数组的一个轴取平均值(E.G 最终得到一个 1xN 数组),同时在平均值计算中排除那些无效值。直觉上我认为

 np.mean(mat1[mask],axis=1)

应该这样做,但是 mat1[mask] 操作产生一个一维数组,它似乎只是 mask 为真的元素 - 当我只想要一个平均值时这无济于事数组的维度。

有没有 'python-esque' 或 numpy 的方法来做到这一点?我想我可以使用掩码将掩码元素设置为 NaN 并使用 np.nanmean - 但这仍然感觉有点笨拙。有没有办法做到这一点 'cleanly'?

我认为最好的方法是:

masked = np.ma.masked_where(mat1 == 0 && mat2 == 0, array_to_mask)

然后用

取平均值
masked.mean(axis=1)

一种同样笨拙但有效的方法是将数组与掩码相乘,将掩码值设置为零。那么当然你必须手动除以非屏蔽值的数量。因此笨拙。但这将适用于整数值数组,这是 nan 情况下不能说的。对于小型和大型阵列(包括另一个答案中的掩码阵列解决方案),它似乎也是最快的:

import numpy as np

def nanny(mat, mask):
    mat = mat.astype(float).copy() # don't mutate the original
    mat[~mask] = np.nan            # mask values
    return np.nanmean(mat, axis=0) # compute mean

def manual(mat, mask):
    # zero masked values, divide by number of nonzeros
    return (mat*mask).sum(axis=0)/mask.sum(axis=0)

# set up dummy data for testing
N,M = 400,400
mat1 = np.random.randint(0,N,(N,M))
mask = np.random.randint(0,2,(N,M)).astype(bool)

print(np.array_equal(nanny(mat1, mask), manual(mat1, mask))) # True