如何在vanilla Python中对列表进行排名?

时间:2015-03-27 06:48:54

标签: python ranking

假设我有一个清单:

[4, 5, 2, 1]

我需要对这些进行排名,输出为:

[3, 4, 2, 1]

如果两个人在这种情况下具有相同的排名:

[4, 4, 2, 3] then the rankings should be averaged -> [3.5, 3.5, 1, 2]

修改
这里的等级代表排序列表中的数字位置。如果有多个具有相同值的数字,则每个这样的数字的等级将是其位置的平均值。

2 个答案:

答案 0 :(得分:2)

可能不是最有效的,但这有效。

  • rank获取一个已排序的列表和一个项目,并通过找到它将被插入的位置来计算该项目的等级之前所有等于它的元素,之后,然后平均两个位置(使用数组二分)。
  • rank_list使用rank来计算所有元素的排名。 partial调用只是为了简化,而不必为每个项目查找再次对列表进行排序。

像这样:

from bisect import bisect_left, bisect_right
from functools import partial

def rank(item, lst):
    '''return rank of item in sorted list'''
    return (1 + bisect_left(lst, item) + bisect_right(lst, item)) / 2.0

def rank_list(lst):
    f = partial(rank, lst=sorted(lst))
    return [f(i) for i in lst]

rank_list([4, 4, 2, 1])
## [3.5, 3.5, 2.0, 1.0]

答案 1 :(得分:0)

我在这里找到了答案: Efficient method to calculate the rank vector of a list in Python

def rank_simple(vector):
    return sorted(range(len(vector)), key=vector.__getitem__)

def rankdata(a):
    n = len(a)
    ivec=rank_simple(a)
    svec=[a[rank] for rank in ivec]
    sumranks = 0
    dupcount = 0
    newarray = [0]*n
    for i in xrange(n):
        sumranks += i
        dupcount += 1
        if i==n-1 or svec[i] != svec[i+1]:
            averank = sumranks / float(dupcount) + 1
            for j in xrange(i-dupcount+1,i+1):
                newarray[ivec[j]] = averank
            sumranks = 0
            dupcount = 0
    return newarray

我想看看是否有更简单或更有效的方法。