问题描述
我希望True
在用作遮罩时会保留ndarray
,但是,它会像None
一样增加尺寸。
arr = np.arange(16).reshape(2,4,2)
np.all(arr[True] == arr) # outputs: True
足够接近,但看起来更近:
arr[True].shape # outputs: (1,2,2)
arr[None].shape # outputs: (1,2)
我发现了两种设置身份掩码的方法:使用slice(None)
或Ellipsis
。
np.all(arr[slice(None)] == arr) # outputs: True
arr[slice(None)].shape # outputs: (2,2)
np.all(Ellipsis == arr) # outputs: True
arr[Ellipsis].shape # outputs: (2,2)
这里没有什么真正令人惊讶的,因为这首先就是切片的工作方式。 slice(None)
有点丑陋,而Ellipsis
似乎有点快。
但是,请执行以下操作:
我不确定我是否完全理解这一点:
从1.15.0版开始不推荐使用:为了保持与Numeric中的常用用法向后兼容,如果选择对象是包含切片的任何非ndarray和非元组序列(例如列表),则也将启动基本切片对象,省略号对象或newaxis对象,但不适用于整数数组或其他嵌入式序列。
我知道保留数组的最佳方法不是屏蔽它,而是说我真的想为屏蔽设置默认值...;-)
问题: 设置身份掩码的首选方法是什么?如果可以的话,True
是否添加尺寸是预期的行为?
解决方法
对于示例二维数组:
In [172]: x=np.array([[1,2],[4,3]])
In [173]: x.__array_interface__
Out[173]:
{'data': (50806320,False),'strides': None,'descr': [('','<i8')],'typestr': '<i8','shape': (2,2),'version': 3}
带有省略号的视图:
In [174]: x[...].__array_interface__
Out[174]:
{'data': (50806320,# same as for x
'strides': None,'version': 3}
具有附加尺寸的视图:
In [175]: x[None].__array_interface__
Out[175]:
{'data': (50806320,'shape': (1,2,'version': 3}
具有附加尺寸的副本-注意更改数据地址。高级索引。
In [176]: x[True].__array_interface__
Out[176]:
{'data': (50796640,'version': 3}
另一个尺寸为0的副本。它正在重用内存。
In [177]: x[False].__array_interface__
Out[177]:
{'data': (50796640,'shape': (0,'version': 3}
在indexing
页上唯一可以找到的参考是:
https://numpy.org/doc/stable/reference/arrays.indexing.html#detailed-notes
布尔数组的非零等价不适用于零维布尔数组。
如果这种行为是过去的实现遗留下来的,我不会感到惊讶。由于合并多个数字包的历史,因此存在一些粗糙的边缘。其中一些已经或正在弃用。
标量布尔索引是zero dimensional boolean array
:
In [178]: np.array(True).shape
Out[178]: ()
我们可以在以下位置添加新维度:
In [181]: x[:,True].shape
Out[181]: (2,1,2)
In [183]: x[...,False].shape
Out[183]: (2,0)
,
您一直在说“掩码”,但听起来根本就不需要掩码操作,即使是“身份”掩码也是如此。遮罩数组通常是形状与原始数组相同的布尔数组,使用遮罩进行索引将生成一维数组,其中包含由遮罩选择的项。即使是完全真实的蒙版,也可以生成应用于它的阵列的平坦副本。这不是身份操作。可以使用遮罩来做奇怪的事情,但是不能执行身份操作。
如果您希望索引器输出与原始数组等效的数组,则典型的,最通用的方法是...
-文字省略号:
arr[...]
与:
不同,这也适用于0维数组。请注意,这将生成一个视图,而不是副本。没有索引器可以产生副本并在所有输入尺寸下正常工作。
arr[True]
的工作方式与主要是出于使0维数组遵循与正维数组遵循相同的布尔索引规则的愿望类似。如上所述,如果使用n维掩码对n维数组进行索引,则结果将是1维数组。如果使用0维掩码对0维数组建立索引,结果将再次为1维数组:
In [1]: import numpy
In [2]: x = numpy.array([[1,[3,4]])
In [3]: x[x % 2 == 0]
Out[3]: array([2,4])
In [4]: y = numpy.array([1,3,4])
In [5]: y[y % 2 == 0]
Out[5]: array([2,4])
In [6]: z = numpy.array(5) # 0-dimensional!
In [7]: z[z % 2 == 0]
Out[7]: array([],dtype=int64)
In [8]: z[z % 2 == 1]
Out[8]: array([5])
使用0维掩码对0维数组进行索引会使维数增加1。一般来说,使用0维掩码对n维数组进行索引会产生n + 1维数组。如果蒙版为True,则额外尺寸的长度为1;否则为0。如果mask为False,则额外维度的长度为0,并且输出中没有元素。这种一般性的行为很少有用,但最适合(极有用)的规则,该规则将正尺寸蒙版应用于尺寸不匹配的数组。