一个numpy数组的True和False索引

4

代码:

import numpy as np    
a = np.arange(5)   
print(a[True])    
print(a[False])

结果:

[[0 1 2 3 4]]
[]

对于上述代码,当我将True传递给numpy数组的索引时,它会返回完整的数组,而当传递False时,则返回一个空数组。背后发生了什么?

请您能否再次检查一下第一个打印语句的输出?它是 [0,1,2,3,4] 还是 [[0,1,2,3,4]] - Paul Panzer
它是[[0 1 2 3 4]]。 - Scarface
2个回答

4
您的示例---将标量或0D布尔掩码应用于1D数组产生的结果是:
print(a[True])
# [[0 1 2 3 4]]
print(a[False])
# []

为了更清楚,特别是针对第二个(False)情况,让我们查询形状。

print(a[True].shape)
# (1, 5)
print(a[False].shape)
# (0, 5)

乍一看,这似乎有点令人困惑。为什么需要额外的维度?

让我们从一个不那么激进的例子开始,然后解释为什么这是逻辑行为:

x = np.arange(6).reshape(3,2)
m2 = np.array([[True,False],[True,True],[False,True]])
m1 = np.array([True,False,True])
m0 = np.array(True)

我们已经创建了一个二维数组和对应的二维、一维、零维掩码。
使用2D掩码进行掩蔽得到1D结果。
x[m2]
# array([0, 2, 3, 5])

使用一维掩码进行掩蔽会选择整行,从而生成二维结果。

x[m1]
# array([[0, 1],
#        [4, 5]])

我们也可以在更高维度上进行验证,从掩码中删除一个维度将使结果加一。

因此,屏蔽0D时,逻辑上应该比我们开始时多一个维度。 2D掩码选择单个点(0D -> 列表:1D),1D掩码选择整行(1D -> 列表:2D)。因此,0D掩码应该并且确实选择整张纸(2D -> 列表:3D);由于基础数组是2D,因此一张纸就是整个数组。

x[m0]
# array([[[0, 1],
#         [2, 3],
#         [4, 5]]])

x[m0].ndim
# 3

总的来说:

x[m2].ndim == x.ndim - m2.ndim + 1
# True 
x[m1].ndim == x.ndim - m1.ndim + 1
# True
x[m0].ndim == x.ndim - m0.ndim + 1
# True

漂亮的展示!我看到了逻辑,对于维度>=1(数组和掩码),这也对我有意义,但如果1D与零维掩码相遮盖,为什么增加维度会有用呢? - FObersteiner
1
在我的经验中,这种一贯的行为是最容易处理的。例如,如果你正在编写一些代码,希望它能处理各种尺寸的数据,那么你可能需要能够预测中间结果的属性。在这种情况下,能够依靠像答案最后给出的公式这样的公式,而不必为0D掩码再进行额外的分支处理,会非常方便。 - Paul Panzer

0
假设您有一个numpy数组,即[0,1,2,3,4]。您需要对索引进行条件判断,如果满足条件则返回该元素,否则舍弃该元素。在这里,您放置了True,这意味着每个元素都满足此条件,在任何情况下都为True。如果是False,则没有元素满足条件。请查看此部分:

布尔或“mask”索引数组


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