I have a list:
somelist = [500, 600, 200, 1000]
I want to generate the rank order of that list:
rankorderofsomelist = [3, 2, 4, 1]
There are some complex solutions, but does anyone have any simple methods?
I have a list:
somelist = [500, 600, 200, 1000]
I want to generate the rank order of that list:
rankorderofsomelist = [3, 2, 4, 1]
There are some complex solutions, but does anyone have any simple methods?
Simplest I can think of:
rankorder = sorted(range(len(thelist)), key=thelist.__getitem__)
This will, of course, produce [2, 1, 3, 0]
, because Python indexing is always zero-based -- if for some absolutely weird reason you need to add one to each index you can of course easily do so:
rankorder_weird = [1+x for x in rankorder]
Since you've tagged this question scipy
, you could use scipy.stats.rankdata
:
>>> rankdata(somelist)
array([ 2., 3., 1., 4.])
>>> len(somelist) - rankdata(somelist)
array([ 2., 1., 3., 0.])
>>> len(somelist) - rankdata(somelist) + 1
array([ 3., 2., 4., 1.])
The real advantage is that you can specify how you want the corner cases to be treated:
>>> rankdata([0,1,1,2])
array([ 1. , 2.5, 2.5, 4. ])
>>> rankdata([0,1,1,2], method='min')
array([ 1, 2, 2, 4])
>>> rankdata([0,1,1,2], method='dense')
array([ 1, 2, 2, 3])
Try this one-liner:
rankorderofsomelist = [sorted(somelist).index(x) for x in somelist]
Note that it'll behave as expected for a list with multiple entries of the same value (e.g. four instances of the same value, all of them the second-largest in the list, will all be ranked 2). Also note that Pythonic sorting is ascending (smallest to largest) and zero-based, so you may have to apply a final pass over the list to increment the ranks, reverse them, etc.
You can include that pass in the one-liner. To yield your desired result, just use:
rankorderofsomelist = [len(somelist)-(sorted(somelist).index(x)) for x in somelist]