0

当我有一个带有布尔索引的结构化掩码数组时,在什么情况下可以获得视图以及何时获得副本?文档说高级索引总是返回一个副本,但这不是真的,因为X[X>0]=42技术上高级索引之类的东西,但分配有效。我的情况比较复杂:

我想根据另一个字段的标准设置特定字段的掩码,因此我需要获取该字段,应用布尔索引并获取掩码。有3个!= 6 次这样做。

准备:

In [83]: M = ma.MaskedArray(random.random(400).view("f8,f8,f8,f8")).reshape(10, 10)

In [84]: crit = M[:, 4]["f2"] > 0.5
  1. 字段 - 索引 - 掩码(失败):

    In [85]: M["f3"][crit, 3].mask = True
    
    In [86]: print(M["f3"][crit, 3].mask)
    [False False False False False]
    
  2. 索引 - 字段 - 掩码(失败):

    In [87]: M[crit, 3]["f3"].mask = True
    
    In [88]: print(M[crit, 3]["f3"].mask)
    [False False False False False]
    
  3. 索引 - 掩码 - 字段(失败):

    In [94]: M[crit, 3].mask["f3"] = True
    
    In [95]: print(M[crit, 3].mask["f3"])
    [False False False False False]
    
  4. 掩码 - 索引 - 字段(失败):

    In [101]: M.mask[crit, 3]["f3"] = True
    
    In [102]: print(M.mask[crit, 3]["f3"])
    [False False False False False]
    
  5. 字段 - 掩码 - 索引(成功):

    In [103]: M["f3"].mask[crit, 3] = True
    
    In [104]: print(M["f3"].mask[crit, 3])
    [ True  True  True  True  True]
    
    # set back to False so I can try method #6
    
    In [105]: M["f3"].mask[crit, 3] = False
    
    In [106]: print(M["f3"].mask[crit, 3])
    [False False False False False]
    
  6. 掩码 - 字段 - 索引(成功):

    In [107]: M.mask["f3"][crit, 3] = True
    
    In [108]: print(M.mask["f3"][crit, 3])
    [ True  True  True  True  True]
    

所以,看起来索引必须排在最后

4

2 回答 2

1

__setitem__v.的问题很重要,但是对于结构化数组和掩码,当 a第一次制作副本__getitem__时,它有点难以分类。__getitem__

关于结构化数组,字段索引是先出现还是元素出现都无关紧要。但是,某些版本似乎在这方面存在错误。我会尝试找到一个最近的 SO question 这是一个问题。

对于掩码数组,存在如何正确修改掩码的问题。.mask是访问底层._mask数组的属性。但这是用__getattr__. 所以简单的setitemvgetitem区别并不直接适用。

让我们先跳过结构化位

In [584]: M = np.ma.MaskedArray(np.arange(4))

In [585]: M
Out[585]: 
masked_array(data = [0 1 2 3],
             mask = False,
       fill_value = 999999)

In [586]: M.mask
Out[586]: False

In [587]: M.mask[[1,2]]=True
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-587-9010ee8f165e> in <module>()
----> 1 M.mask[[1,2]]=True

TypeError: 'numpy.bool_' object does not support item assignment

最初mask是一个标量布尔值,而不是一个数组。

这有效

In [588]: M.mask=np.zeros((4,),bool)  # change mask to array

In [589]: M
Out[589]: 
masked_array(data = [0 1 2 3],
             mask = [False False False False],
       fill_value = 999999)

In [590]: M.mask[[1,2]]=True

In [591]: M
Out[591]: 
masked_array(data = [0 -- -- 3],
             mask = [False  True  True False],
       fill_value = 999999)

这不

In [592]: M[[1,2]].mask=True

In [593]: M
Out[593]: 
masked_array(data = [0 -- -- 3],
             mask = [False  True  True False],
       fill_value = 999999)

M[[1,2]]显然是副本,并且分配是对其mask属性,而不是M.mask.

……

掩码数组有.__setmask__方法。你可以在np.ma.core.py. 并且掩码属性定义为

mask = property(fget=_get_mask, fset=__setmask__, doc="Mask")

所以M.mask=...也用这个。

所以看起来问题案例正在做

M.__getitem__(index).__setmask__(values)

因此副本。正在M.mask[]=...

M._mask.__setitem__(index, values)

因为_getmask只是return self._mask


M["f3"].mask[crit, 3] = True

之所以有效,是因为M['f3']它是一种观点。(M[['f1','f3']]可用于获取,但不适用于设置)。

M.mask["f3"]也是一种看法。我不完全确定相关获取和设置的顺序。 __setmask__具有专门处理复合 dtype(结构化)的代码。

==========================

查看结构化数组,没有屏蔽复杂性,索引顺序很重要

In [607]: M1 = np.arange(16).view("i,i")

In [609]: M1[[3,4]]['f1']=[3,4]          # no change   
In [610]: M1[[3,4]]['f1']
Out[610]: array([7, 9], dtype=int32)

In [611]: M1['f1'][[3,4]]=[1,2]    # change
In [612]: M1
Out[612]: 
array([(0, 1), (2, 3), (4, 5), (6, 1), (8, 2), (10, 11), (12, 13), (14, 15)], dtype=[('f0', '<i4'), ('f1', '<i4')])

所以我们还是有 a__getitem__后跟 a 的__setitem__,我们要注意 get 是返回视图还是副本。

于 2016-06-15T19:37:52.913 回答
0

这是因为虽然高级索引返回一个副本,但分配给高级索引仍然有效。只有高级索引是最后一个操作的方法才分配给高级索引(通过__setitem__)。

于 2016-06-15T17:36:00.417 回答