使用索引数组从任意维度的ndarray中提取2d ndarray



我想基于某些维度的索引位置数组提取numpy ndarray的部分。让我在的例子中展示一下

示例数据

dummy = np.random.rand(5,2,100)
X = np.array([[0,1],[4,1],[2,0]])

dummy是维度为5x2x100的原始ndarray。这个维度是任意的,也可以是5x2x4x100。
X是索引值的矩阵,这里X[:,0]dummy的第一维度的索引,X[:,1]是第二维度的索引。X中的列数始终是dummy中的维度数减去1。

示例输出

我想为这个例子提取以下形式的ndarray

[
dummy[0,1,:],
dummy[4,1,:],
dummy[2,0,:]
]

并发症

如果dummy中的维度数量是固定的,那么这可以通过dummy[X[:,0],X[:,1],:]来完成。遗憾的是,维度可能不同,例如,dummy可能是5x2x4x6x100 ndarray,相应地,X可能是3x4。我处理这一问题的努力没有取得预期的结果。

  • dummy[X,:]在本例中产生了与dummy[X]相同的3x2x100 ndarray
  • 通过对i执行类似于dummy = dummy[X[:,i],:]的操作来迭代减少dummy——在X的列数上的迭代器也不会减少示例中超过3x2x100的ndarray

我有一种感觉,使用numpy索引应该很简单,但我想我在搜索解决方案时错过了正确的术语
有人能解决这个问题吗?

我将尝试为@Michael Szczesny的回答提供一些可解释性。

首先,请注意,如果您有一个维度为nnp.array,并在其中传递m<nm索引,那么它将与在维度>=m中使用:相同。在您的情况下,例如:

dummy[(0, 0)] == dummy[0, 0, :]

鉴于此,请注意,您还可以将数组作为索引进行传递。因此:

dummy[([0, 1], [0, 0])]

它将与相同

np.array([dummy[(0,0)], dummy[(1,0)]])

您可以使用进行验证

dummy[([0, 1], [0, 0])] == np.array([dummy[(0,0)], dummy[(1,0)]])

最后,请注意:

(*X.T,)
# (array([0, 4, 2]), array([1, 1, 0]))

你在这里得到每个维度作为一个数组,然后你会得到:

[
dummy[0,1],
dummy[4,1],
dummy[2,0]
]

与相同

[
dummy[0,1,:],
dummy[4,1,:],
dummy[2,0,:]
]

编辑:您可以使用元组(X.T(,而不是使用(*X.T,(,这对我来说更有意义

正如Michael Szczesny所写,最好的解决方案是dummy[(*X.T,)]

由于X[:,0]dummy的第一维度的索引,X[:,1]dummy的第二维度的索引。如果将X(X.T(进行换位,则dummy的第一维度索引将为X.T[0]dummy的第二维索引将为X.T[1]

现在,要根据需要对dummy进行切片,可以通过以下方式指定第一维度和第二维度的索引:

dummy[(first_dim_indices, second_dim_indices)] = dummy[(X.T[0], X.T[1])]

为了简化代码(并且由于您不想将X矩阵转置两次(,您可以将元组中的X.T解压缩为(*X.T,),因此编写X[(*X.T,)]与编写dummy[(X.T[0], X.T[1])]是一样的。

如果您有不固定数量的维度要通过槽进行切片,则这种编写也很有用,因为您将从X.T中打开与dummy中要切片的维度一样多的行。例如,假设您想从dummy中检索一个1D数组,给定以下索引:

first_dim:  (0, 4, 2)
second_dim: (1, 1, 0)
third_dim:  (9, 8, 7)

您可以将3个维度的索引指定为X = np.array([[0,1,9],[4,1,8],[2,0,7]]),并且dim[(*X.T,)]仍然有效。

最新更新