【问题标题】:Ranking a List of Numbers对数字列表进行排名
【发布时间】:2015-05-02 06:44:45
【问题描述】:

我有一个清单:

 somelist = [500, 600, 200, 1000]

我想生成该列表的排名顺序:

 rankorderofsomelist = [3, 2, 4, 1]

some complex solutions,但是有没有人有什么简单的方法?

【问题讨论】:

标签: python scipy


【解决方案1】:

由于您已将此问题标记为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.])

真正的优势是您可以指定如何处理极端情况:

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

【讨论】:

  • 这工作得非常好,并且使用这种方法是因为 tie 处理方法 'min'
【解决方案2】:

我能想到的最简单的:

rankorder = sorted(range(len(thelist)), key=thelist.__getitem__)

这当然会产生[2, 1, 3, 0],因为 Python 索引始终是从零开始的——如果出于某种绝对奇怪的原因您需要为每个索引添加一个,您当然可以轻松地这样做:

rankorder_weird = [1+x for x in rankorder]

【讨论】:

  • 不,这会产生[2, 0, 1, 3]
【解决方案3】:

试试这个单行:

rankorderofsomelist = [sorted(somelist).index(x) for x in somelist]

请注意,对于具有相同值的多个条目的列表,它将按预期运行(例如,相同值的四个实例,它们都是列表中的第二大实例,都将排在第 2 位)。另请注意,Pythonic 排序是升序(从小到大)和从零开始的,因此您可能必须对列表应用最后一遍以增加排名、反转排名等。

您可以将该通行证包含在单行中。要产生您想要的结果,只需使用:

rankorderofsomelist = [len(somelist)-(sorted(somelist).index(x)) for x in somelist]

【讨论】:

  • 这很好用。它不像 scipy 方法那样处理关系,但我没有在问题中指定。
  • 如果我没记错的话,这具有 N^3log(N) 的复杂性:对于列表中的每个项目,您都在对列表进行排序,然后线性搜索该特定项目。即使您之前对列表进行了排序,而不是在循环中,您仍然会查看 N^2 复杂度。你could do worse,但你必须非常努力。这是一个可怕的建议。 -1,恐怕……
  • @Jaime OP 要求一个简单的解决方案,所以我给他看了一个。此外,降低时间复杂度微不足道:只需将sorted(somelist) 存储在单行代码上方的变量中即可。这会产生 O(n^2) 的最坏情况复杂度。
猜你喜欢
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
相关资源
最近更新 更多