You can use numpy.argsort
multiple times to handle a matrix, as suggested in this answer on SO.
import numpy as np
inp = np.array([[9,4,15,0,18],
[16,19,8,10,1]])
inp.ravel().argsort().argsort().reshape(inp.shape)
array([[4, 2, 6, 0, 8],
[7, 9, 3, 5, 1]])
What is a rank matrix?
In summary, if I were to take all the integers in the matrix, and sort them smallest to largest, then assign each one a rank
from 0 to 9, that would result in the rank matrix. Notice that the smallest is 0 which gets a rank of 0, while largest is 19, which gets the last rank of 9.
How the double argsort works
#printing them so they align nicely
print('Array ->', end='')
for i in inp.ravel().astype('str'):
print(i.center(4), end='')
print('\n')
print('Sort1 ->', end='')
for i in inp.ravel().argsort().astype('str'):
print(i.center(4), end='')
print('\n')
print('Sort2 ->', end='')
for i in inp.ravel().argsort().argsort().astype('str'):
print(i.center(4), end='')
Array -> 9 4 15 0 18 16 19 8 10 1
Sort1 -> 3 9 1 7 0 8 2 5 4 6
Sort2 -> 4 2 6 0 8 7 9 3 5 1
Let's first summarize what argsort
does. It takes the position of each element and puts them where they belong after sorting. Knowing this, we can write a backward logic which is sort of triangular in nature. Lets start from sort2, then sort1 and then array.
0th
(in sort2) is 4th
(in sort1), 4th
(in sort1) is 0th
(in array). So 0th
(in array) is 0th
(in sort2)
9th
(in sort2) is 1st
(in sort1), 1st
(in sort1) is 9th
(in array). So, 9th
(in array) is 9th
(in sort2)
6th
(in sort2) is 9th
(in sort1), 9th
(in sort1) is 6th
(in array). So, 6th
(in array) is 6th
(in sort2)
Its a bit confusing to wrap your head around it, but once you can understand how argsort() works, you shouldn't have a problem.