python - 布尔索引行为的解释
问题描述
对于二维数组 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, 2, 4],
::
])
print(y[
[True, False, True, False, True],
::
])
---
[[ 0 1 2 3]
[ 8 9 10 11]
[16 17 18 19]]
问题
请帮助了解产生结果的规则或机制。
用元组替换[]
会产生一个形状为 (0, 5, 4) 的空数组。
y[
(True, False, True, False, True)
]
---
array([], shape=(0, 5, 4), dtype=int64)
使用单个True
添加一个新轴。
y[True]
---
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]]])
y[True].shape
---
(1, 5, 4)
添加额外的布尔值 True 产生相同的结果。
y[True, True]
---
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]]])
y[True, True].shape
---
(1, 5, 4)
但是,添加 False boolean 会再次导致空数组。
y[True, False]
---
array([], shape=(0, 5, 4), dtype=int64)
不确定文档解释了这种行为。
通常,如果索引包含布尔数组,则结果与将 obj.nonzero() 插入同一位置并使用上述整数数组索引机制相同。x[ind_1, boolean_array, ind_2] 等价于 x[(ind_1,) + boolean_array.nonzero() + (ind_2,)]。
如果只有一个布尔数组而没有整数索引数组,这很简单。只需要注意确保布尔索引的维度与它应该使用的维度一样多。
解决方案
布尔标量索引没有详细记录,但您可以跟踪它在源代码中的处理方式。例如,请参阅numpy 源代码中的此注释和相关代码:
/*
* 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中引入的,作者在此评论中概述了动机;粗略地说,目的是在过滤操作的输出中提供一致性。例如:
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中找不到任何关于它的讨论。
鉴于此,我建议考虑这种行为定义不明确,并避免它以支持有据可查的索引方法。
推荐阅读
- solr - Solr 中的自定义提升
- asp.net-core - Razor pages asp-page tag helper没有按预期工作
- reactjs - Antd datepicker(date.clone 不是函数)
- python - Plotly Express:使用 DataFrame 列中的特征颜色绘制散点图 MapBox (px.scatter_mapbox)
- laravel - 如何获取引导下拉按钮的选定值
- json - 是否有让 Firebase 实时数据库不将数据转换为数组的标志?
- python - 在 Azure DevOps Pipeline 中找不到 Pytest
- eclipse - 无法访问“kotlin.String”的超类型“java.io.Serializable”。检查您的模块类路径是否存在缺失或冲突的依赖项
- reactjs - 反应传单。映射 CircleMarker 数组进入无限循环
- javascript - 谷歌分析没有发送带有浏览量点击的自定义维度