当我有一个带有布尔索引的结构化蒙版数组时,在什么条件下我会得到一个视图,什么时候能得到一个副本? documentation表示高级索引始终返回副本,但事实并非如此,因为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
字段 - 索引 - 掩码(失败):
In [85]: M["f3"][crit, 3].mask = True
In [86]: print(M["f3"][crit, 3].mask)
[False False False False False]
索引 - 字段 - 掩码(失败):
In [87]: M[crit, 3]["f3"].mask = True
In [88]: print(M[crit, 3]["f3"].mask)
[False False False False False]
索引 - 掩码 - 字段(失败):
In [94]: M[crit, 3].mask["f3"] = True
In [95]: print(M[crit, 3].mask["f3"])
[False False False False False]
掩码 - 索引 - 字段(失败):
In [101]: M.mask[crit, 3]["f3"] = True
In [102]: print(M.mask[crit, 3]["f3"])
[False False False False False]
字段 - 掩码 - 索引(成功):
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]
掩码 - 字段 - 索引(成功):
In [107]: M.mask["f3"][crit, 3] = True
In [108]: print(M.mask["f3"][crit, 3])
[ True True True True True]
因此,看起来索引必须 last 。
答案 0 :(得分:1)
__setitem__
v。__getitem__
的问题非常重要,但对于结构化数组和屏蔽,当__getitem__
首次制作副本时,更难以理清。
关于结构化数组,字段索引首先出现还是元素都不重要。但是,某些版本似乎在这方面存在错误。我试着找一个最近的SO问题,这是一个问题。
使用蒙版数组,存在如何正确修改蒙版的问题。 .mask
是访问基础._mask
数组的属性。但这是用__getattr__
获取的。因此,简单的setitem
v getitem
区别并不直接适用。
让我们先跳过结构化的比特
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属性用
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')])
因此,我们仍然有__getitem__
后跟__setitem__
,我们必须注意get是返回视图还是副本。
答案 1 :(得分:0)
这是因为虽然高级索引会返回副本,但将分配给高级索引仍然有效。只有高级索引是 last 操作的方法才能分配高级索引(通过__setitem__
)。