Numpy 高级索引和基本索引

Posted

技术标签:

【中文标题】Numpy 高级索引和基本索引【英文标题】:Numpy Advanced Indexing and basic indexing 【发布时间】:2018-08-31 06:50:27 【问题描述】:

我正在尝试了解this article 的特定部分。

高级索引的定义意味着x[(1,2,3),]x[(1,2,3)] 根本不同。后者相当于x[1,2,3],它将触发基本选择,而前者将触发高级索引。请务必了解发生这种情况的原因。

我已经尝试过以下代码。

>>> import numpy as np 
>>> a = np.arange(50).reshape(5,10)    
>>> b = a[(2,2)]    
>>> bb = a[(2,2),]    
>>> a[2,2] = 50 # a[2,2] was 22 in the first place 
>>> b
22  # this outcome confuses me!

我认为b = a[(2,2)] 会获得视图,所以当我更改a[2,2] 时会这样做。

bb = a[(2,2),] 会收到副本,所以即使我在 a 上做某事也不会发生任何事情。

但是当我将 a[2,2] 从 22 更改为 50 时

我期望 b = a[(2,2)] 将更改为 50 a 而bb = a[(2,2),] 将保持不变。

这一切有什么问题?我是否误解或遗漏了重要的东西?

如果是,请指正并提前感谢!

【问题讨论】:

【参考方案1】:

“基本选择”(即索引而不是切片)不会创建视图,而是创建副本。为了成为一个视图,您需要传递一个单元素切片(切片与索引不同,始终是一个视图)。

import numpy as np 
a = np.arange(50).reshape(5,10)    
b = a[2:3,2:3].squeeze()    
a[2,2] = 50 
b

array(50)

您也可以使用b = a[2, 2, None].squeeze() 获得相同的结果,它会触发“花式”索引”,这是选择和切片之间的一种混合并重新生成视图。使用“高级”索引(就像您所做的那样,或者如b = a[[2],[2]]) 是索引的变体,并返回一个副本。

是的,保持这些不同类型的索引对初学者来说并不容易。并且创建一个元素的视图仍然是一种 hacky。在大多数情况下,像 array(50) 这样的 0-dim 数组可以像普通的 int 一样使用。

为了更令人困惑,a[2,2] 在等号左侧被解释为视图,而不是在右侧。它与= 被解释为.__setitem__() 有关。

【讨论】:

我想我理解你的大部分答案,但你能解释一下 b = a[2, 2, None].squeeze() ,索引末尾的 None 代表什么?我前几天才看到这个,但仍然无法弄清楚这是什么!谢谢! 我使用类似 b=a[2,2,...] 的操作,似乎返回视图!这两个操作(:和...)是否真的触发了基本索引? 是的,a[2,2,...] 触发花式索引,因为... 本质上意味着“包括所有其他维度”,即使没有其他维度,它也算作一个切片。由于您随后混合了切片和索引,因此它被认为是“花哨的”并且它返回一个视图。可能是最好的解决方案,因为它不需要squeeze() : 只会在实际存在维度时触发精美的索引。如果你这样做a[2,2,:],你会得到一个IndexError,因为a没有第三维度 None 添加了另一个维度(它与np.newaxis 相同,但写起来更短),它被认为是一个切片。然后,您可以使用 squeeze() 摆脱该维度

以上是关于Numpy 高级索引和基本索引的主要内容,如果未能解决你的问题,请参考以下文章

numpy数组的动态高级索引

张量流中张量对象的非连续索引切片(高级索引,如numpy)

(数据分析三板斧)第一斧Numpy-第三节:索引和切片

numpy广播机制,取特定行特定列的元素 的高级索引取法

大数据清洗2(元素操作)

给定一个 numpy 数组视图中项目的索引,在基本数组中找到它的索引