Using python 3.x I would like to achieve dense rank(do not skip number if the ranks are repeated ). I have the below array sorted according to score
rank_list = [{'Id': 236966, 'score': 91.0}, {'Id': 237241, 'score': 82.0}, {'Id': 237077, 'score': 79.0}, {'Id': 237084, 'score': 78.0}, {'Id': 237080, 'score': 72.0}, {'Id': 237236, 'score': 71.0}, {'Id': 236979, 'score': 71.0}, {'Id': 236909, 'score': 67.0}, {'Id': 237174, 'score': 67.0}, {'Id': 237035, 'score': 66.0}]
I used the below code to calculate and assign the 'rank' field but the code skips a rank if there is a rank repeated
def rankFunc(e):
return e['score']
rank_list.sort(key = rankFunc, reverse=True)
sorted_scores = [obj['score'] for obj in rank_list]
ranks = [sorted_scores.index(x) for x in sorted_scores]
for index, obj in enumerate(rank_list):
obj['rank'] = ranks[index]+1
the current output:
rank = [1, 2, 3, 4, 5, 6, 6, 8, 8, 10]
I would like ranks to be assigned without skipping any number like below,
rank = [1, 2, 3, 4, 5, 6, 6, 7, 7, 8]
This little helper function should solve your problem:
def rank_unique(x, **kwargs):
sx = sorted(set(x), **kwargs)
invsx = {s: i for i, s in enumerate(sx)}
return [1 + invsx[v] for v in x]
>>> rank_unique([r["score"] for r in rank_list], reverse=True)
[1, 2, 3, 4, 5, 6, 6, 7, 7, 8]