解决方案:
>>> a[np.arange(np.shape(a)[0])[:,np.newaxis], np.argsort(a)]
array([[1, 2, 3],
[2, 8, 9]])
你说得对,虽然我不会将其描述为欺骗索引。
也许这将有助于使其更清晰:
In [544]: i=np.argsort(a,axis=1)
In [545]: i
Out[545]:
array([[1, 2, 0],
[2, 0, 1]])
i 是我们想要的每一行的顺序。那就是:
In [546]: a[0, i[0,:]]
Out[546]: array([1, 2, 3])
In [547]: a[1, i[1,:]]
Out[547]: array([2, 8, 9])
要同时执行两个索引步骤,我们必须对第一个维度使用“列”索引。
In [548]: a[[[0],[1]],i]
Out[548]:
array([[1, 2, 3],
[2, 8, 9]])
另一个可以与i配对的数组是:
In [560]: j=np.array([[0,0,0],[1,1,1]])
In [561]: j
Out[561]:
array([[0, 0, 0],
[1, 1, 1]])
In [562]: a[j,i]
Out[562]:
array([[1, 2, 3],
[2, 8, 9]])
如果i 标识每个元素的列,则j 指定每个元素的行。 [[0],[1]] 列数组也可以正常工作,因为它可以针对 i 进行广播。
我想到了
np.array([[0],
[1]])
作为j 的“速记”。它们一起定义了新数组的每个元素的源行和列。它们一起工作,而不是按顺序工作。
从a 到新数组的完整映射为:
[a[0,1] a[0,2] a[0,0]
a[1,2] a[1,0] a[1,1]]
def foo(a):
i = np.argsort(a, axis=1)
return (np.arange(a.shape[0])[:,None], i)
In [61]: foo(a)
Out[61]:
(array([[0],
[1]]), array([[1, 2, 0],
[2, 0, 1]], dtype=int32))
In [62]: a[foo(a)]
Out[62]:
array([[1, 2, 3],
[2, 8, 9]])