如何获得一个numpy数组中的N个最大值的索引?

Numpy提出了一种通过np.argmax得到数组最大值索引的np.argmax

我想要一个类似的东西,但是返回N个最大值的索引。

例如,如果我有一个数组[1, 3, 2, 4, 5] ,它的function(array, n=3)将返回[4, 3, 1]

谢谢 :)

我能够想到的最简单的方法是:

 In [1]: import numpy as np In [2]: arr = np.array([1, 3, 2, 4, 5]) In [3]: arr.argsort()[-3:][::-1] Out[3]: array([4, 3, 1]) 

这涉及到一个完整的数组。 我不知道numpy提供了一个内置的方式来做一个部分sorting; 到目前为止,我还没有find一个。

如果这个解决scheme变得太慢(特别是对于小n ),可能值得在Cython中编码。

较新的NumPy版本(1.8及以上)有一个称为argpartition的function。 为了得到四个最大元素的指标,

 >>> a array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0]) >>> ind = np.argpartition(a, -4)[-4:] >>> ind array([1, 5, 8, 0]) >>> a[ind] array([4, 9, 6, 9]) 

argsort不同的argsort ,这个函数在最坏的情况下以线性时间运行,但是返回的索引没有被sorting,从评估a[ind]的结果可以看出。 如果你也需要这个,请在​​后面进行分类:

 >>> ind[np.argsort(a[ind])] array([1, 8, 5, 0]) 

为了以这种方式获得sorting顺序的top- k元素,需要O( n + k log k )时间。

编辑:修改包括Ashwini乔杜里的改进。

 >>> import heapq >>> import numpy >>> a = numpy.array([1, 3, 2, 4, 5]) >>> heapq.nlargest(3, range(len(a)), a.take) [4, 3, 1] 

对于常规Python列表:

 >>> a = [1, 3, 2, 4, 5] >>> heapq.nlargest(3, range(len(a)), a.__getitem__) [4, 3, 1] 

如果您使用Python 2,请使用xrange而不是range

资料来源: http : //docs.python.org/3/library/heapq.html

更简单:

 idx = (-arr).argsort()[:n] 

其中n是最大值的数量。

如果你碰巧正在处理一个multidimensional array,那么你需要将这些索引展平:

 def largest_indices(ary, n): """Returns the n largest indices from a numpy array.""" flat = ary.flatten() indices = np.argpartition(flat, -n)[-n:] indices = indices[np.argsort(-flat[indices])] return np.unravel_index(indices, ary.shape) 

例如:

 >>> xs = np.sin(np.arange(9)).reshape((3, 3)) >>> xs array([[ 0. , 0.84147098, 0.90929743], [ 0.14112001, -0.7568025 , -0.95892427], [-0.2794155 , 0.6569866 , 0.98935825]]) >>> largest_indices(xs, 3) (array([2, 0, 0]), array([2, 2, 1])) >>> xs[largest_indices(xs, 3)] array([ 0.98935825, 0.90929743, 0.84147098]) 

如果你不关心第K个最大的元素的顺序 ,你可以使用argpartition ,它应该比通过argsort的完整sortingargsort

 K = 4 # we want the indeces of the four largest values a = np.array([0, 8, 0, 4, 5, 8, 8, 0, 4, 2]) np.argpartition(a,-K)[-K:] array([4, 1, 5, 6]) 

感谢这个问题 。

我跑了一些testing,它看起来argpartitionargsort的大小和K的值增加。

这将比完整sorting更快,具体取决于原始数组的大小和select的大小:

 >>> A = np.random.randint(0,10,10) >>> A array([5, 1, 5, 5, 2, 3, 2, 4, 1, 0]) >>> B = np.zeros(3, int) >>> for i in xrange(3): ... idx = np.argmax(A) ... B[i]=idx; A[idx]=0 #something smaller than A.min() ... >>> B array([0, 2, 3]) 

当然,这涉及到篡改你的原始数组。 您可以通过复制或replace原始值来修复(如果需要)。 …对于您的使用情况,以较低者为准。

bottleneck有一个部分sorting的function,如果sorting整个数组只是为了得到N个最大值的代价太大。

我对这个模块一无所知。 我刚刚GOOGLE了numpy partial sort

对于multidimensional array,您可以使用axis关键字来沿预期坐标轴应用分区。

 # For a 2D array indices = np.argpartition(arr, -N, axis=1)[:, -N:] 

并抓取物品:

 x = arr.shape[0] arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N) 

但请注意,这不会返回一个sorting的结果。 在这种情况下,您可以沿预期的轴使用np.argsort()

 indices = np.argsort(arr, axis=1)[:, -N:] # result x = arr.shape[0] arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N) 

这里是一个例子:

 In [42]: a = np.random.randint(0, 20, (10, 10)) In [44]: a Out[44]: array([[ 7, 11, 12, 0, 2, 3, 4, 10, 6, 10], [16, 16, 4, 3, 18, 5, 10, 4, 14, 9], [ 2, 9, 15, 12, 18, 3, 13, 11, 5, 10], [14, 0, 9, 11, 1, 4, 9, 19, 18, 12], [ 0, 10, 5, 15, 9, 18, 5, 2, 16, 19], [14, 19, 3, 11, 13, 11, 13, 11, 1, 14], [ 7, 15, 18, 6, 5, 13, 1, 7, 9, 19], [11, 17, 11, 16, 14, 3, 16, 1, 12, 19], [ 2, 4, 14, 8, 6, 9, 14, 9, 1, 5], [ 1, 10, 15, 0, 1, 9, 18, 2, 2, 12]]) In [45]: np.argpartition(a, np.argmin(a, axis=0))[:, 1:] # 1 is because the first item is the minimum one. Out[45]: array([[4, 5, 6, 8, 0, 7, 9, 1, 2], [2, 7, 5, 9, 6, 8, 1, 0, 4], [5, 8, 1, 9, 7, 3, 6, 2, 4], [4, 5, 2, 6, 3, 9, 0, 8, 7], [7, 2, 6, 4, 1, 3, 8, 5, 9], [2, 3, 5, 7, 6, 4, 0, 9, 1], [4, 3, 0, 7, 8, 5, 1, 2, 9], [5, 2, 0, 8, 4, 6, 3, 1, 9], [0, 1, 9, 4, 3, 7, 5, 2, 6], [0, 4, 7, 8, 5, 1, 9, 2, 6]]) In [46]: np.argpartition(a, np.argmin(a, axis=0))[:, -3:] Out[46]: array([[9, 1, 2], [1, 0, 4], [6, 2, 4], [0, 8, 7], [8, 5, 9], [0, 9, 1], [1, 2, 9], [3, 1, 9], [5, 2, 6], [9, 2, 6]]) In [89]: a[np.repeat(np.arange(x), 3), ind.ravel()].reshape(x, 3) Out[89]: array([[10, 11, 12], [16, 16, 18], [13, 15, 18], [14, 18, 19], [16, 18, 19], [14, 14, 19], [15, 18, 19], [16, 17, 19], [ 9, 14, 14], [12, 15, 18]]) 
 from operator import itemgetter from heapq import nlargest result = nlargest(N, enumerate(your_list), itemgetter(1)) 

现在结果列表将包含N个元组(索引,值),其中值被最大化