如何使用另一个ndarray的行索引ndarray?

时间:2015-08-08 18:02:00

标签: python numpy

如果我有

x = np.arange(1, 10).reshape((3,3))
# array([[1, 2, 3],
#        [4, 5, 6],
#        [7, 8, 9]])

ind = np.array([[1,1], [1,2]])
# array([[1, 1],
#        [1, 2]])

,如何使用ind的每一行(轴0)来提取x的单元格?我希望最终得到数组[5, 6]np.take(x, ind, axis=0)似乎不起作用。

2 个答案:

答案 0 :(得分:1)

您可以通过使用两个整数数组索引x来使用"advanced integer indexing",第一个数组用于索引行,第二个数组用于索引列:

In [58]: x[ind[:,0], ind[:,1]]
Out[58]: array([5, 6])

答案 1 :(得分:0)

x[ind.T.tolist()]

也适用,也可以用于多维NumPy数组。

为什么?

NumPy数组由元组索引。通常,这些元组是created implicitly by python

  

注意

     

在Python中,x[(exp1, exp2, ..., expN)]相当于x[exp1, exp2, ..., expN];,后者只是前者的语法糖。

请注意,这种语法糖不是特定于NumPy的。当密钥是元组时,你可以在字典上使用它:

In [1]: d = { 'I like the number': 1, ('pi', "isn't"): 2}

In [2]: d[('pi', "isn't")]
Out[2]: 2

In [3]: d['pi', "isn't"]
Out[3]: 2

实际上,它甚至与索引无关:

In [5]: 1, 2, 3
Out[5]: (1, 2, 3)

因此,对于您的NumPy数组,x = np.arange(1,10).reshape((3,3))

In [11]: x[1,2]
Out[11]: 6

,因为

In [12]: x[(1,2)]
Out[12]: 6

因此,在unutbu's answer中,实际上传递了一个包含ind列的元组:

In [21]: x[(ind[:,0], ind[:,1])]
Out[21]: array([5, 6])

x[ind[:,0], ind[:,1]]只是同等的(和推荐的)简写符号。

这就是元组的样子:

In [22]: (ind[:,0], ind[:,1])
Out[22]: (array([1, 1]), array([1, 2]))

我们可以从ind不同地构造相同的元组:tolist()返回NumPy数组的行。转置切换行和列,因此我们可以通过首先转置并在结果上调用tolist来获取列列表:

In [23]: ind.T.tolist()
Out[23]: [[1, 1], [1, 2]]

因为ind在您的示例中是对称的,所以它是自己的转置。因此,为了说明,我们使用

In [24]: ind_2 = np.array([[1,1], [1,2], [0, 0]])
# array([[1, 1],
#        [1, 2],
#        [0, 0]])

In [25]: ind_2.T.tolist()
Out[25]: [[1, 1, 0], [1, 2, 0]]

这很容易转换为我们想要的元组:

In [27]: tuple(ind_2.T.tolist())
Out[27]: ([1, 1, 0], [1, 2, 0])

In [28]: tuple(ind.T.tolist())
Out[28]: ([1, 1], [1, 2])

因此,

In [29]: x[tuple(ind.T.tolist())]
Out[29]: array([5, 6])

等同于unutbu对x.ndim == 2ind_2.shape[1] == 2的回答,但在x.ndim == ind_2.shape[1]时也更常用,以防您必须使用多维NumPy数组。

为什么你可以删除tuple(...)并直接使用列表进行索引,我不知道。必须是NumPy的东西:

In [43]: x[ind_2.T.tolist()]
Out[43]: array([5, 6, 1])