Chr*_*rgo 2 python scipy python-2.7
我有一个清单:
somelist = [500, 600, 200, 1000]
Run Code Online (Sandbox Code Playgroud)
我想生成该列表的排名顺序:
rankorderofsomelist = [3, 2, 4, 1]
Run Code Online (Sandbox Code Playgroud)
有一些复杂的解决方案,但有人有任何简单的方法吗?
既然您已经标记了这个问题scipy,您可以使用scipy.stats.rankdata:
>>> rankdata(somelist)
array([ 2., 3., 1., 4.])
>>> len(somelist) - rankdata(somelist)
array([ 2., 1., 3., 0.])
>>> len(somelist) - rankdata(somelist) + 1
array([ 3., 2., 4., 1.])
Run Code Online (Sandbox Code Playgroud)
真正的优点是您可以指定如何处理极端情况:
>>> rankdata([0,1,1,2])
array([ 1. , 2.5, 2.5, 4. ])
>>> rankdata([0,1,1,2], method='min')
array([ 1, 2, 2, 4])
>>> rankdata([0,1,1,2], method='dense')
array([ 1, 2, 2, 3])
Run Code Online (Sandbox Code Playgroud)
我能想到的最简单的:
rankorder = sorted(range(len(thelist)), key=thelist.__getitem__)
Run Code Online (Sandbox Code Playgroud)
这当然会产生[2, 1, 3, 0],因为 Python 索引总是从零开始的——如果出于某种绝对奇怪的原因你需要为每个索引添加一个,你当然可以很容易地这样做:
rankorder_weird = [1+x for x in rankorder]
Run Code Online (Sandbox Code Playgroud)
试试这个单行:
rankorderofsomelist = [sorted(somelist).index(x) for x in somelist]
Run Code Online (Sandbox Code Playgroud)
请注意,对于具有相同值的多个条目的列表,它的行为将符合预期(例如,相同值的四个实例,它们都是列表中的第二大实例,将全部排名为 2)。另请注意,Pythonic 排序是升序(从小到大)且从零开始的,因此您可能必须对列表应用最后一次遍历以增加排名、反转排名等。
您可以将该传球包含在一行中。要产生您想要的结果,只需使用:
rankorderofsomelist = [len(somelist)-(sorted(somelist).index(x)) for x in somelist]
Run Code Online (Sandbox Code Playgroud)