有效地查找Python数组/列表中N个最大元素的索引

时间:2012-10-08 18:48:34

标签: python performance numpy

如果这是一个重复的问题,我很抱歉,我查找了这些信息,但仍然无法找到它。

是否可以通过非常有效地使用递减顺序的N个最大元素的索引来排列numpy数组(或python列表)?

例如,数组:

a = array([4, 1, 0, 8, 5, 2])

按降序排列的最大元素的索引将给出(考虑N = 6,包括所有元素):

8 - > 3

5 - > 4

4 - > 0

2 - > 5

1 - > 1

0 - > 2

result = [3, 4, 0, 5, 1, 2]

我知道如何使用一种有点愚蠢的方法(比如对数组进行排序并搜索其索引中每个N个数字),但我想知道是否有任何有效的库,如瓶颈或heapq或者pythonic这种方法非常快。我必须在几个阵列中应用它,每个阵列有300k元素,这就是性能问题的原因。

提前致谢!

更新

我读了答案并决定使用300k的随机整数来计算它们,结果如下:

解决方案1: sorted(range(len(a)), key=lambda i:a[i]) 时间: 230毫秒

解决方案2: heapq.nlargest(len(a), zip(a, itertools.count())) 时间:396 ms

解决方案3: heapq.nlargest(len(a), enumerate(a), key=operator.itemgetter(1)) 时间: 864 ms

解决方案4: def f(a,N): return np.argsort(a)[::-1][:N] (N = len(a)) 时间:104毫秒

非常感谢快速而又非常好的答案!

4 个答案:

答案 0 :(得分:19)

您是否看过内置的numpy argsort方法?:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html

我可以使用该方法在我的机器上在大约29毫秒内对300,000随机浮点数组合排序。

def f(a,N):
    return np.argsort(a)[::-1][:N]

答案 1 :(得分:11)

L = [4, 1, 0, 8, 5, 2]
sorted(range(len(L)), key=lambda i:L[i])

答案 2 :(得分:5)

您可以使用heapq轻松完成此操作:

>>> heapq.nlargest(3, zip(a, itertools.count()))
[(8, 3), (5, 4), (4, 5)]

通过对第一个值进行排序来排序元组,然后对第二个值进行排序等等...这意味着我们可以简单地创建一个(value, index)元组并进行排序,为我们提供值的索引(值为也给了,但我们可以很容易地扔掉它们。)

我使用zip()itertools.count()作为枚举为我们提供了错误的顺序,因此它们将按索引排序,而不是按值排序。或者,您也可以((value, index) for index, value in enumerate(a)),但我觉得不太清楚。

另一种方法是提供密钥,执行heapq.nlargest(3, enumerate(a), key=operator.itemgetter(1))

答案 3 :(得分:0)

使用heapq的另一种方法

heapq.nlargest(n, range(len(a)), key=a.__getitem__)

正如其他地方所评论的那样,除非a非常大并且n<<len(a),否则它不会超过排序,因为排序在Python中是一个相对较快的操作。然而,最终慢速O(n)总是会超过O(n * log(n))