【问题标题】:Indexing a numpy array with a numpy array of indexes [duplicate]用一个numpy索引数组索引一个numpy数组[重复]
【发布时间】:2018-10-25 23:59:04
【问题描述】:

我有一个 3D numpy 数组 data 和另一个索引数组 pos(索引本身就是一个 numpy 数组,这使得后一个数组成为 2D 数组):

import numpy as np
data = np.arange(8).reshape(2, 2, -1)
#array([[[0, 1],
#    [2, 3]],
#
#  [[4, 5],
#    [6, 7]]])

pos = np.array([[1, 1, 0], [0, 1, 0], [1, 0, 0]])
#array([[1, 1, 0],
#       [0, 1, 0],
#       [1, 0, 0]])

我想使用来自pos 的索引来选择和/或改变来自data 的元素。我可以使用for 循环或列表理解来进行选择:

[data[tuple(i)] for i in pos]
#[6, 2, 4]
data[[i for i in pos.T]]
#array([6, 2, 4])

但这似乎不是一种麻木的方式。这个问题有向量化的numpy解决方案吗?

【问题讨论】:

  • 您是否关心该方法是否返回视图与副本?
  • 从技术上讲不是一个完全的骗局。但是所有相关信息都在那里。如果您想重新打开它,请告诉我。
  • 如果您对答案或受骗不满意,请在此处 ping 我们中的任何一个。我们很乐意重新开放并为此提供赏金,以激励更聪明的人提出尚不存在的解决方案;-)
  • @piRSquared 找到了一个完全正确的骗子。
  • @Divakar 谢谢

标签: python arrays numpy indexing


【解决方案1】:

您可以将pos 拆分为 3 个单独的数组和索引,如下所示——

>>> i, j, k = pos.T
>>> data[i, j, k]
array([6, 2, 4])

这里pos的列数对应data的深度。只要您处理 3D 矩阵,获得ijk 就不会比这更复杂了。

在 python-3.6+ 上,您可以将其缩短为——

>>> data[[*pos.T]]
array([6, 2, 4])

【讨论】:

  • 哎呀,投反对票的人请让我知道这个答案在语义上是否有任何问题(据我所知,这给了 OP 他们所期望的)。我想纠正它!谢谢。
  • 从某种意义上说,您正在做[i for i in pos.T],只是您的解决方案仅适用于 3 个项目。我担心的是列表理解在这里似乎没有必要。难道没有原生的numpy方式来重组数组吗?
  • tensorflow 有 tf.gather_nd。没有numpy的类比吗?
  • 是的。我对这个答案投了反对票,并开始使用 take 发布我自己的答案,然后意识到它不起作用并删除了我的反对票。对不起Coldspeed
  • @MFisherKDX 好吧,如果 OP 不介意 python-3.6 解决方案,我已经添加了它。