【问题标题】:How do I rank a list in vanilla Python?如何在 vanilla Python 中对列表进行排名?
【发布时间】:2015-03-27 06:48:53
【问题描述】:

假设我有一个列表:

[4, 5, 2, 1]

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

[3, 4, 2, 1]

如果两个在case中排名相同:

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

编辑
这里 rank 代表数字在排序列表中的位置。如果有多个具有相同值的数字,则每个数字的排名将是它们的位置的平均值。

【问题讨论】:

  • 如果两个以上的排名相同怎么办?
  • 排名是什么意思?
  • 如果两个以上的排名相同,则将所有排名平均。
  • 排名在哪个位置,即1st、2nd、3rd...

标签: python ranking


【解决方案1】:

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

  • 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]

【讨论】:

  • 我在这里列出了 3 个项目的两个解决方案:我在下面发布的解决方案的运行时间延长了 59%
【解决方案2】:

我在这里找到了答案: 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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 2023-01-11
    相关资源
    最近更新 更多