2

我正在研究numpy 问题 2972​​ 和几个相关问题。事实证明,所有这些问题都与数组本身是结构化的情况有关,但它的掩码不是:

In [38]: R = numpy.zeros(10, dtype=[("A", "<f2"), ("B", "<f4")])

In [39]: Rm = numpy.ma.masked_where(R["A"]<5, R)

In [41]: Rm.dtype
Out[41]: dtype([('A', '<f2'), ('B', '<f4')])

In [42]: Rm.mask.dtype
Out[42]: dtype('bool')

# Now, both `__getitem__` and `__repr__` will result in errors — see issue #2972

如果我以不同方式创建掩码数组,则掩码 dtype 的结构类似于数组本身的 dtype:

In [44]: Q.dtype
Out[44]: dtype([('A', '<f4'), ('B', '<f4')])

In [45]: Q.mask.dtype
Out[45]: dtype([('A', '?'), ('B', '?')])

前一种情况暴露出几个问题。例如,Rm.__repr__()并且Rm["A"]两者都导致IndexError,尽管它ValueError在过去是 a。

按照设计,模式是否应该是可能的,在哪里A.dtype是结构化的,但A.mask.dtype不是结构化的?

换句话说:是__repr____getitem__方法中的错误numpy.ma.core.MaskedArray,还是真正的错误发生在之前 - 通过首先允许这样一个屏蔽的结构化数组存在?

4

1 回答 1

3

第一种情况下的错误表明方法期望掩码与基本数组具有相同数量(和名称)的字段

__getitem__:  dout._mask = _mask[indx]
_recursive_printoption: (curdata, curmask) = (result[name], mask[name])

如果掩码数组是使用“主”构造函数创建的,则掩码具有相同的结构

Rn = np.ma.masked_array(R, mask=R['A']>5)
Rn.mask.dtype: dtype([('A', '?'), ('B', '?')])

换句话说,每个元素的每个字段都有一个掩码值。

masked_array文档显然打算使用“相同形状”来包括dtype结构。 Mask: Must be convertible to an array of booleans with the same shape as 'data'.

如果我尝试以相同的方式设置masked_where掩码

Rn._mask=R['A']>5

我得到同样的打印错误。结构化掩码被新的布尔值覆盖,改变了它的 dtype。相反,如果我使用

Rn.mask=R['A']<5

Rn打印良好。.mask是一个属性,其set方法显然可以正确处理结构化掩码。

在不深入研究代码历史记录(在 github 上)的情况下,我的猜测是,这masked_where是一个在将结构 dtypes 添加到ma代码的其他部分时没有更新的便利功能。与之相比,ma.masked_array它是一个根本不看 dtype 的简单函数。其他便利功能,例如ma.masked_greateruse masked_where。更改result._mask = condresult.mask = cond可能是纠正此问题所需的全部内容。


您对非结构化面罩的后果进行了多彻底的测试?

Rm.flatten()

返回一个带有结构化掩码的数组,即使它以非结构化掩码开头。那是因为它使用Rm.__setmask__对字段敏感的 . 这就是该属性的set功能。mask

Rm.tolist()  # same error as str()

masked_where以。。开始:

cond = make_mask(condition)

make_mask返回简单的 'bool' dtype。也可以使用 dtype 调用它,生成结构化掩码:np.ma.make_mask(R['A']<5,dtype=R.dtype). 但是这样的结构化掩码在masked_where. masked_where不仅允许非结构化掩码,它还强制它是非结构化的。

您的非结构化掩码已经部分实现,recordmask属性:

recordmask = property(fget=_get_recordmask)

我说部分是因为它有一个get方法,但该set方法尚未实现。看def _set_recordmask(self):

我越看这个,我就越相信这masked_where是错误的。可以将其更改为设置结构化掩码,但与masked_array. 如果在数组是结构化的(has)时引发错误,它可能会更好dtype.names。这种方式masked_where对于非结构化数值数组仍然有用,同时防止误用到结构化数组。

我还应该看看测试代码。

于 2015-01-28T18:10:02.663 回答