Search code examples
kdb+rankingrankranking-functions

q kdb rank function with duplicated ranks


What would be an implementation of a q kdb function that does the same thing as the rank function but returns duplicated rank numbers for equal values?

In the standard implementation

rank 2 7 4 3 19 16 15 20 25 16 19

gives:

0 3 2 1 7 5 4 9 10 6 8

But I am looking for:

0 3 2 1 6 5 4 7 8 5 6

Solution

  • Can do that by using distinct to remove duplicates, applying rank to that list and then creating a dictionary to map those rankings back to the original list.

    q)list:2 7 4 3 19 16 15 20 25 16 19
    
    / creating the dictionary
    q)d!rank d:distinct list
    2 | 0
    7 | 3
    4 | 2
    3 | 1
    19| 6
    16| 5
    15| 4
    20| 7
    25| 8
    
    / wrapping this up in a function
    q)rankDistinct:{(d!rank d:distinct x)x}
    
    / applying to the list
    q)rankDistinct list
    0 3 2 1 6 5 4 7 8 5 6
    

    Or alternatively you could sort the distinct elements and then use find ? to get the ranking by finding the index of where list elements appear in the distinct sorted elements.

    q)rankDistinct2:{(asc distinct x)?x}
    
    q)rankDistinct2 list
    0 3 2 1 6 5 4 7 8 5 6