I have a python dictionary:
x = {\'a\':10.1,\'b\':2,\'c\':5}
How do I go about ranking and returning the rank value? Like getting back:
First sort by value in the dict, then assign ranks. Make sure you sort reversed, and then recreate the dict with the ranks.
from the previous answer :
import operator
x={'a':10.1,'b':2,'c':5}
sorted_x = sorted(x.items(), key=operator.itemgetter(1), reversed=True)
out_dict = {}
for idx, (key, _) in enumerate(sorted_x):
out_dict[key] = idx + 1
print out_dict
If I understand correctly, you can simply use sorted
to get the ordering, and then enumerate
to number them:
>>> x = {'a':10.1, 'b':2, 'c':5}
>>> sorted(x, key=x.get, reverse=True)
['a', 'c', 'b']
>>> {key: rank for rank, key in enumerate(sorted(x, key=x.get, reverse=True), 1)}
{'b': 3, 'c': 2, 'a': 1}
Note that this assumes that the ranks are unambiguous. If you have ties, the rank order among the tied keys will be arbitrary. It's easy to handle that too using similar methods, for example if you wanted all the tied keys to have the same rank. We have
>>> x = {'a':10.1, 'b':2, 'c': 5, 'd': 5}
>>> {key: rank for rank, key in enumerate(sorted(x, key=x.get, reverse=True), 1)}
{'a': 1, 'b': 4, 'd': 3, 'c': 2}
but
>>> r = {key: rank for rank, key in enumerate(sorted(set(x.values()), reverse=True), 1)}
>>> {k: r[v] for k,v in x.items()}
{'a': 1, 'b': 3, 'd': 2, 'c': 2}
You could do like this,
>>> x = {'a':10.1,'b':2,'c':5}
>>> m = {}
>>> k = 0
>>> for i in dict(sorted(x.items(), key=lambda k: k[1], reverse=True)):
k += 1
m[i] = k
>>> m
{'a': 1, 'c': 2, 'b': 3}
Using scipy.stats.rankdata:
[ins] In [55]: from scipy.stats import rankdata
[ins] In [56]: x = {'a':10.1, 'b':2, 'c': 5, 'd': 5}
[ins] In [57]: dict(zip(x.keys(), rankdata([-i for i in x.values()], method='min')))
Out[57]: {'a': 1, 'b': 4, 'c': 2, 'd': 2}
[ins] In [58]: dict(zip(x.keys(), rankdata([-i for i in x.values()], method='max')))
Out[58]: {'a': 1, 'b': 4, 'c': 3, 'd': 3}
@beta, @DSM scipy.stats.rankdata has some other 'methods' for ties also that may be more appropriate to what you are wanting to do with ties.
In [23]: from collections import OrderedDict
In [24]: mydict=dict([(j,i) for i, j in enumerate(x.keys(),1)])
In [28]: sorted_dict = sorted(mydict.items(), key=itemgetter(1))
In [29]: sorted_dict
Out[29]: [('a', 1), ('c', 2), ('b', 3)]
In [35]: OrderedDict(sorted_dict)
Out[35]: OrderedDict([('a', 1), ('c', 2), ('b', 3)])
One way would be to examine the dictionary for the largest value, then remove it, while building a new dictionary:
my_dict = x = {'a':10.1,'b':2,'c':5}
i = 1
new_dict ={}
while len(my_dict) > 0:
my_biggest_key = max(my_dict, key=my_dict.get)
new_dict[my_biggest_key] = i
my_dict.pop(my_biggest_key)
i += 1
print new_dict