NumPy: 通过数组索引数组

4
>>> idx = np.random.randint(2, size=(9, 31))
>>> a = np.random.random((9, 31, 2))
>>> a[idx].shape
(9, 31, 31, 2)

为什么上述代码不能返回至少形状为(9, 31, 1),甚至更好的是(9, 31)?如何根据idx中的值获取所需选择? 更新 这里可能有一个更具体、更类比的例子:假设有这个数组。
a = np.asarray([[1, 2], [3, 4], [5, 6], [7, 8]])

如何选择数组[1, 4, 5, 8]的元素(即每行的第0个、第1个、第0个、第1个元素)?

2个回答

4

我认为这就是你想要的:

>>> a[np.arange(9)[:, None], np.arange(31), idx].shape
(9, 31)

对于您的第二个示例,您需要执行以下操作:

>>> a[np.arange(4), [0, 1, 0, 1]]
array([1, 4, 5, 8])

阅读 文档 关于花式索引,特别是在没有每个维度的索引数组时会发生什么情况 这里:那些额外的 np.arange 数组被放置在那里以避免该行为。
还要注意它们如何被重塑(使用 [:, None] 进行索引等同于 .reshape(-1, 1)),以便它们的广播形状具有所需输出数组的形状。

换句话说,np.arange() 确保选择每一行。但是为什么 a[:, [0, 1, 0, 1]] 不同(应用 Python 的索引逻辑(这可能对于 numpy 是错误的))?我真的很想避免为选择过程创建一个新数组(np.arange)。 - orange
1
如果你将Python的索引逻辑应用于a[:, [0, 1, 0, 1]],它会引发一个TypeError: indices must be integers, not tuple...;-) 在NumPy中,“a[:, [0, 1, 0, 1]]”的意思是“对于a的每一行,创建一个四项数组,其中包含该行的第一个、第二个、再次是第一个和第二个元素。”因此,实际上没有替代创建np.arange数组的方法。它仍然非常快,所以你真的不需要担心它。 - Jaime
确实,它看起来与Python的索引非常不同。感谢您提供numpy的翻译。a[np.arange(4), [0, 1, 0, 1]]是什么意思?直觉上对我来说它仍然与[:,]相同... - orange
1
因为 np.arange(4)[0, 1, 0, 1] 具有相同的形状,并且每个维度都有一个数组,所以返回值将是具有相同形状 (4,) 的数组,其中每个数组用于索引它所占据的维度,即你将得到一个包含 [a[0, 0], a[1, 1], a[2, 0], a[3, 1]] 的数组。这很棘手,甚至难以理解,但一旦掌握了它,它就非常、非常强大。 - Jaime
非常感谢您深入浅出的解释。我正在慢慢地理解中...;-) - orange

-1

你正在对ndarray http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#advanced-indexing 进行高级索引。

高级索引总是被广播和迭代为一个:

这是因为在你的情况下,ndarray索引中的元素数量不等于你要索引的ndarray的维数。实际上,你正在产生切片的外积:你索引中的每个元素都会产生一个被索引数组的切片,而不是一个元素。

更新:

>>> map(lambda idx: a[idx[0],idx[1]], [[0,0], [1,1], [2,0], [3,1]])

这将返回:

[1, 4, 5, 8]

哦...这不是我想要的。我更愿意它返回数组上的视图。但是我怎么能使用数组来确定被选择的索引呢? - orange
我更感兴趣的是用 numpy 方法进行选择。创建另一个列表不可行,因为数组非常大。 - orange

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