在Numpy中逐行索引

per*_*iae 13 python indexing numpy

我有两个矩阵,A并且B:

A = array([[2., 13., 25., 1.], [ 18., 5., 1., 25.]])
B = array([[2, 1], [0, 3]])
Run Code Online (Sandbox Code Playgroud)

我想索引每一行的A每一行B,产生切片:

array([[25., 13.], [18., 25.]])
Run Code Online (Sandbox Code Playgroud)

也就是说,我基本上想要这样的东西:

array([A[i,b] for i,b in enumerate(B)])
Run Code Online (Sandbox Code Playgroud)

有没有办法直接指出这个?我能做的最好的就是这个"平板黑客":

A.flat[B + arange(0,A.size,A.shape[1])[:,None]]
Run Code Online (Sandbox Code Playgroud)

ask*_*han 10

@Ophion的答案很棒,值得赞扬,但我想补充一些解释,并提供更直观的结构.

而不是旋转B然后旋转结果,最好只旋转arange.我认为这提供了最直观的解决方案,即使它需要更多的字符:

A[((0,),(1,)), B]
Run Code Online (Sandbox Code Playgroud)

或者等价的

A[np.arange(2)[:, None], B]
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为这里真正发生的是你正在制作一个i数组和一个j数组,每个数组都有与你想要的结果相同的形状.

i = np.array([[0, 0],
              [1, 1]])
j = B
Run Code Online (Sandbox Code Playgroud)

但你可以使用

i = np.array([[0],
              [1]])
Run Code Online (Sandbox Code Playgroud)

因为它会广播匹配B(这是np.arange(2)[:,None]给出的).

最后,使其更一般的(不知道2arange大小),你也可以生成iB

i = np.indices(B.shape)[0]
Run Code Online (Sandbox Code Playgroud)

但是你建立ij,你只需要调用它像

>>> A[i, j]
array([[ 25.,  13.],
       [ 18.,  25.]])
Run Code Online (Sandbox Code Playgroud)


Dan*_*iel 7

不漂亮但是:

A[np.arange(2),B.T].T
array([[ 25.,  13.],
       [ 18.,  25.]])
Run Code Online (Sandbox Code Playgroud)