Search code examples
pythonlistpython-2.7ranking

Ranking a list without breaking ties in Python


I need to attribute ranks to elements of a list while making sure tied elements get the same rank.

For instance:

data = [[1],[3],[2],[2]]

c = 0

for i in sorted(data, reverse=True):
    i.append(c+1)
    c += 1

print data

returns:

[[1, 4], [3, 1], [2, 2], [2, 3]]

Where a rank is appended to the score.

What would I need to change to this simple code to instead obtain:

[[1, 3], [3, 1], [2, 2], [2, 2]]

Where elements scoring 2 are tied and both obtain the second place, while 1, the previously fourth place, is promoted to third place?


Solution

  • Using itertools.groupby, enumerate:

    >>> from itertools import groupby
    >>> data = [[1],[3],[2],[2]]
    >>> sorted_data = sorted(data, reverse=True)
    >>> for rank, (_, grp) in enumerate(groupby(sorted_data, key=lambda xs: xs[0]), 1):
    ...     for x in grp:
    ...         x.append(rank)
    ...
    >>> print data
    [[1, 3], [3, 1], [2, 2], [2, 2]]