python使用非唯一值的平均排名对值列表进行排名

时间:2012-12-07 20:31:28

标签: python

是否有更多的pythonic,更快的想要按值排名字典并平均非唯一值的排名。我的方法:

d = {'a':5,'b':5,'c':5,'d':1,'e':6}
ordered_keys = sorted(d, key=d.get)
ordered_v = [d[k] for k in ordered_keys]
value_rank = [(ordered_v.index(v)+1)+(ordered_v.count(v)-1)/2 for v in ordered_v]
ranked_key_list = zip(ordered_keys,value_rank)
[('d', 1), ('a', 3), ('c', 3), ('b', 3), ('e', 5)]

关于排序词典的广泛讨论非常有用:python dictionary values sorting

3 个答案:

答案 0 :(得分:3)

你所拥有的是非常好的,我怀疑有一个更短的解决方案。

就效率而言,重复使用list.index()list.count()可能会降低大数据集的速度。

如果您要为大量数据执行此操作,那么这个替代实现应该更有效:

from itertools import groupby

d = {'a':5,'b':5,'c':5,'d':1,'e':6}
ranked_key_list = []
i = 1
for k, g in groupby(sorted(d.keys(), key=d.get), key=d.get):
    g = list(g)
    rank = i + (len(g)-1) / 2
    ranked_key_list.extend((k, rank) for k in g)
    i += len(g)

答案 1 :(得分:3)

你算法的瓶颈是.index和.count是O(n)的事实,因此你的瓶颈是这一行:

value_rank = [(ordered_v.index(v)+1)+(ordered_v.count(v)-1)/2 for v in ordered_v]

使您的整体表现为O(n ^ 2)

我为你做了一个O(n * log(n))算法(瓶颈现在是排序):

import collections

d = {'a':5,'b':5,'c':5,'d':1,'e':6}
my_d = collections.defaultdict(list)
for key, val in d.items():
    my_d[val].append(key)

ranked_key_list = [] 
n = v = 1
for _, my_list in sorted(my_d.items()):
    v = n + (len(my_list)-1)/2 
    for e in my_list:
        n += 1
        ranked_key_list.append((e, v))

答案 2 :(得分:0)

key_list = zip(dict.keys(), dict.values())
ranked_key_list = sorted(key_list, key=lambda x: x[1])

编辑:刚刚意识到我没有做平均值的事情....你能澄清一点吗?如何平均3 5s = 3 ??