Search code examples
pythonarraysnumpyrank

How to construct a rank array with numpy? (What is a rank array?)


In my python class, we are learning how to use Numpy, so we got an assignment about that. My question is this: What is a rank array and how can I construct that with using python? My instructor tried to explain that with these lines but I did not understand anything actually :( These are the instructions:

rank_calculator(A) - 5 pts

Given a numpy ndarray A, return its rank array.

Input: [[ 9 4 15 0 18]
        [16 19 8 10 1]]

Return value: [[4 2 6 0 8]
               [7 9 3 5 1]]

The return value should be an ndarray of the same size and shape as the original array A.

So, can someone explain that?


Solution

  • 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.

    1. 0th (in sort2) is 4th (in sort1), 4th (in sort1) is 0th (in array). So 0th (in array) is 0th (in sort2)

    2. 9th (in sort2) is 1st (in sort1), 1st (in sort1) is 9th (in array). So, 9th (in array) is 9th (in sort2)

    3. 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.