微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

布尔索引行为的解释

如何解决布尔索引行为的解释

对于二维数组 y:

y = np.arange(20).reshape(5,4)
---
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]]

所有索引都选择第 1、第 3 和第 5 行。这很清楚。

print(y[
    [0,2,4],::
])
print(y[
    [0,::
])
print(y[
    [True,False,True,True],::
])
---
[[ 0  1  2  3]
 [ 8  9 10 11]
 [16 17 18 19]]

问题

请帮助了解产生结果的规则或机制。

元组替换 [] 会产生一个形状为 (0,5,4) 的空数组。

y[
    (True,True)
]
---
array([],shape=(0,4),dtype=int64)

使用单个 True 添加一个新轴。

y[True]
---
array([[[ 0,1,3],[ 4,6,7],[ 8,9,10,11],[12,13,14,15],[16,17,18,19]]])


y[True].shape
---
(1,4)

添加额外的布尔值 True 会产生相同的结果。

y[True,True]
---
array([[[ 0,19]]])

y[True,True].shape
---
(1,4)

但是,添加 False 布尔值会再次导致空数组。

y[True,False]
---
array([],dtype=int64)

不确定文档解释了这种行为。

一般来说,如果一个索引包含一个布尔数组,结果将是 等同于将 obj.nonzero() 插入相同的位置并使用 上面描述的整数数组索引机制。 x[ind_1,boolean_array,ind_2] 等价于 x[(ind_1,) + boolean_array.nonzero() + (ind_2,)]。

如果只有一个布尔数组而没有整数索引数组 目前,这是直截了当的。只需要注意使 确保布尔索引的维数与它的维数完全一样 应该一起工作。

解决方法

布尔标量索引没有详细记录,但您可以在源代码中跟踪它是如何处理的。例如,请参阅 numpy source 中的此注释和相关代码:

/*
* This can actually be well defined. A new axis is added,* but at the same time no axis is "used". So if we have True,* we add a new axis (a bit like with np.newaxis). If it is
* False,we add a new axis,but this axis has 0 entries.
*/

因此,如果索引是标量布尔值,则会添加一个新轴。如果值为 True,则轴的大小为 1,如果值为 False,则轴的大小为零。

这种行为是在numpy#3798中引入的,作者在this comment中概述了动机;粗略地说,目的是提供过滤操作输出的一致性。例如:

x = np.ones((2,2))
assert x[x > 0].ndim == 1

x = np.ones(2)
assert x[x > 0].ndim == 1

x = np.ones(())
assert x[x > 0].ndim == 1  # scalar boolean here!

有趣的是,第一个之后的任何后续标量布尔值都不会添加额外的维度!从实现的角度来看,这似乎是由于连续的 0D 布尔索引被视为等同于连续的花式索引(即 HAS_0D_BOOL 在某些情况下被视为 HAS_FANCY),因此以相同的方式组合作为花哨的指数。从逻辑的角度来看,这种极端情况下的行为似乎不是故意的:例如,我在 numpy#3798 中找不到任何关于它的讨论。

鉴于此,我建议考虑这种定义不明确的行为,并避免使用记录良好的索引方法。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。