1

I am trying to sort this array,

[[15 12 10 8 7]
[7 8 4 3 1]
[8 5 9 12 4]
[6 10 14 7 5]] 

to

[[5 4 3 2 1]
[4 5 3 2 1]
[3 2 4 5 1]
[2 4 5 3 1]]

I have tried using nm.argsort(a, axis=1) but this doesn't give desired output, may be I am using it incorrectly. The same operation would apply to second array but at column level. Any help would be appreciated. Thanks.

Divakar
  • 218,885
  • 19
  • 262
  • 358
Apu Dar
  • 13
  • 4

1 Answers1

1

It seems you are trying to trace back the elements positions in the sorted order.

Approach #1 : One way to do so would be to use argsort twice, like so -

a.argsort(1).argsort(1)+1

Approach #2 : Efficient method inspired by this post -

def argsort_unique2D(idx):
    m,n = idx.shape
    sidx = np.empty((m,n),dtype=int)
    sidx[np.arange(m)[:,None], idx] = np.arange(n)
    return sidx

out = argsort_unique2D(a.argsort(1))+1

Sample run -

In [42]: a
Out[42]: 
array([[15, 12, 10,  8,  7],
       [ 7,  8,  4,  3,  1],
       [ 8,  5,  9, 12,  4],
       [ 6, 10, 14,  7,  5]])

In [43]: a.argsort(1).argsort(1)+1
Out[43]: 
array([[5, 4, 3, 2, 1],
       [4, 5, 3, 2, 1],
       [3, 2, 4, 5, 1],
       [2, 4, 5, 3, 1]])

In [71]: argsort_unique2D(a.argsort(1))+1
Out[71]: 
array([[5, 4, 3, 2, 1],
       [4, 5, 3, 2, 1],
       [3, 2, 4, 5, 1],
       [2, 4, 5, 3, 1]])

Runtime test -

In [76]: a = np.random.rand(100,10000)

In [77]: %timeit a.argsort(1).argsort(1)+1
10 loops, best of 3: 115 ms per loop

In [78]: %timeit argsort_unique2D(a.argsort(1))+1
10 loops, best of 3: 67.8 ms per loop
Divakar
  • 218,885
  • 19
  • 262
  • 358