argsort为多维ndarray

Dil*_*rix 10 python arrays sorting numpy numerical-methods

我试图让索引按最后一个轴排序一个多维数组,例如

>>> a = np.array([[3,1,2],[8,9,2]])
Run Code Online (Sandbox Code Playgroud)

我想要这样的指数i,

>>> a[i]
array([[1, 2, 3],
       [2, 8, 9]])
Run Code Online (Sandbox Code Playgroud)

根据numpy.argsort的文档,我认为它应该这样做,但我收到错误:

>>> a[np.argsort(a)]
IndexError: index 2 is out of bounds for axis 0 with size 2
Run Code Online (Sandbox Code Playgroud)

编辑:我需要以相同的方式重新排列相同形状的其他数组(例如,b这样的数组a.shape == b.shape)......这样

>>> b = np.array([[0,5,4],[3,9,1]])
>>> b[i]
array([[5,4,0],
       [9,3,1]])
Run Code Online (Sandbox Code Playgroud)

hpa*_*ulj 10

解:

>>> a[np.arange(np.shape(a)[0])[:,np.newaxis], np.argsort(a)]
array([[1, 2, 3],
       [2, 8, 9]])
Run Code Online (Sandbox Code Playgroud)

你做对了,虽然我不会把它描述为欺骗索引.

也许这有助于使其更清晰:

In [544]: i=np.argsort(a,axis=1)

In [545]: i
Out[545]: 
array([[1, 2, 0],
       [2, 0, 1]])
Run Code Online (Sandbox Code Playgroud)

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])
Run Code Online (Sandbox Code Playgroud)

要同时执行两个索引步骤,我们必须为第一维使用"列"索引.

In [548]: a[[[0],[1]],i]
Out[548]: 
array([[1, 2, 3],
       [2, 8, 9]])
Run Code Online (Sandbox Code Playgroud)

另一个可以配对的阵列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]])
Run Code Online (Sandbox Code Playgroud)

如果i标识每个元素的列,则j指定每个元素的行.该[[0],[1]]柱阵列的作品一样好,因为它可以防止广播i.

我想

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

作为'短手' j.它们一起定义新数组的每个元素的源行和列.他们一起工作,而不是顺序.

a从新阵列到完整的映射是:

[a[0,1]  a[0,2]  a[0,0]
 a[1,2]  a[1,0]  a[1,1]]
Run Code Online (Sandbox Code Playgroud)
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]])
Run Code Online (Sandbox Code Playgroud)

  • 我扩展了我的解释。 (2认同)

小智 6

上面的答案现在有点过时了,因为 numpy 1.15 中添加了新功能以使其更简单;take_along_axis ( https://docs.scipy.org/doc/numpy-1.15.1/reference/ generated/numpy.take_along_axis.html ) 允许您执行以下操作:

>>> a = np.array([[3,1,2],[8,9,2]])
>>> np.take_along_axis(a, a.argsort(axis=-1), axis=-1)
array([[1 2 3]
       [2 8 9]])
Run Code Online (Sandbox Code Playgroud)