Numpy掩码数组求和

4

我希望对于一个完全被屏蔽的数组的总和,结果应该是零,但是却返回“屏蔽”。我该如何让函数返回零?

>>> a = np.asarray([1, 2, 3, 4])
>>> b = np.ma.masked_array(a, mask=~(a > 2))
>>> b
masked_array(data = [-- -- 3 4],
             mask = [ True  True False False],
       fill_value = 999999)

>>> b.sum()
7
>>> b = np.ma.masked_array(a, mask=~(a > 5))
>>> b
masked_array(data = [-- -- -- --],
         mask = [ True  True  True  True],
   fill_value = 999999)


>>> b.sum()
masked
>>> np.ma.sum(b)
masked
>>> 

这里有另一件出乎意料的事情:

>>> b.sum() + 3
masked
1个回答

4
在您的最后一个案例中:
In [197]: bs=b1.sum()
In [198]: bs.data
Out[198]: array(0.0)
In [199]: bs.mask
Out[199]: array(True, dtype=bool)
In [200]: repr(bs)
Out[200]: 'masked'
In [201]: str(bs)
Out[201]: '--'

如果我指定keepdims,那么我将获得一个不同的数组:
In [208]: bs=b1.sum(keepdims=True)
In [209]: bs
Out[209]: 
masked_array(data = [--],
             mask = [ True],
       fill_value = 999999)
In [210]: bs.data
Out[210]: array([0])
In [211]: bs.mask
Out[211]: array([ True], dtype=bool)

以下是与sum代码相关的部分:

def sum(self, axis=None, dtype=None, out=None, keepdims=np._NoValue):
    kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}

    _mask = self._mask
    newmask = _check_mask_axis(_mask, axis, **kwargs)
    # No explicit output
    if out is None:
        result = self.filled(0).sum(axis, dtype=dtype, **kwargs)
        rndim = getattr(result, 'ndim', 0)
        if rndim:
            result = result.view(type(self))
            result.__setmask__(newmask)
        elif newmask:
            result = masked
        return result
    ....

It's the

 newmask = np.ma.core._check_mask_axis(b1.mask, axis=None)
 ...
 elif newmask: result = masked

在你的情况下,产生masked值的行。当所有的值都被屏蔽时,newmask为True,而如果有些值没有被屏蔽,则为False。选择返回np.ma.masked是故意的。

计算的核心是:

In [218]: b1.filled(0).sum()
Out[218]: 0

剩下的代码决定是返回一个标量还是遮罩数组。
============
另外,针对您的补充:
In [232]: np.ma.masked+3
Out[232]: masked

看起来np.ma.masked是一个特殊的数组,可以在计算中传播自己。有点像np.nan


我期望返回一个标量值,而不是一个数组(我要的是所有维度上的总和)。 - orange
1
我添加了sum代码的相关部分。当输入完全被屏蔽时,我可以理解返回值可能存在一些歧义。我不知道是否有任何关于这是否正确的争论。如果您不喜欢结果,可以将sum应用于b.filled(0) - hpaulj
看起来推理是,“如果所有值都被掩盖,即使总和的起始值为0,它也无法给出适当的标量值”。 - hpaulj
有趣。感谢你挖掘出来。你与 np.nan 的比较非常准确。我想我可以按照你的写法做 b.filled(0).sum() - orange
@hpaulj 是的,因为我认为遮蔽数组背后的推理和主要观点之一出现在文档中,并且其中一个经常出现的词是“无效”和标量,例如0,在一般情况下可能是有效的返回值。所以他们可能试图保持谨慎。 - fedepad
@fedepad @hpaulj:我知道他们把它当作类似于np.nan的处理方式,但是这样就应该有一个特殊的sum()函数,比如nansum() - orange

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接