Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
高效地查找Python数组/列表中N个最大元素的索引_Python_Performance_Numpy - Fatal编程技术网

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

高效地查找Python数组/列表中N个最大元素的索引,python,performance,numpy,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 我知道如何使用一种有点愚蠢的方法(比如对数组进行排序并搜索N个数字中的每一个作为索引),但我想知道是否有任何有效的库,比如

如果这是一个重复的问题,我提前表示歉意,我查找了此信息,但仍然找不到

是否可以通过使用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

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

提前谢谢

更新

我阅读了答案并决定使用300k随机整数计时,结果如下:

解决方案1:
排序(范围(len(a)),键=λi:a[i])
时间:230毫秒

解决方案2:
heapq.nlagest(len(a),zip(a,itertools.count())
时间:396毫秒

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

解决方案4:
def(a,N):返回np.argsort(a)[:-1][:N](N=len(a))
时间:104 ms


非常感谢您快速且非常好的回答

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

L = [4, 1, 0, 8, 5, 2]
sorted(range(len(L)), key=lambda i:L[i])
>>> heapq.nlargest(3, zip(a, itertools.count()))
[(8, 3), (5, 4), (4, 5)]
元组按第一个值排序,然后按第二个值排序,依此类推。。。这意味着我们可以简单地创建
(value,index)
的元组并进行排序,为我们提供值的索引(也提供了值,但我们可以很容易地丢弃这些值)

我使用的是
zip()
itertools.count()
,因为enumerate给了我们错误的顺序,所以它们将按索引排序,而不是按值排序。或者,您也可以对索引执行
((值,索引),枚举中的值(a))
,但我觉得这不太清楚


另一种选择是给出一个键,执行
heapq.nlargest(3,enumerate(a),key=operator.itemgetter(1))

您看过内置的numpy
argsort
方法了吗

我可以用这种方法在我的机器上用大约29毫秒的时间对一个有300000个随机浮点数的数组进行排序

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

使用heapq的另一种方法

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


正如其他地方所评论的,除非a非常大并且
n比我聪明,否则它不会超过排序+1给你,先生。
key=L.uu getitem\uuu
是一个替代方案(在某些情况下可能会快一点)。@GarethRees:你说得对!我没想到
lambda
s/are/slowI尝试了一个简单的测试,并没有看到太大的差异,所以使用
lambda
不会有错。我尝试使用getitem使其工作,但由于我是python的新手,无法使其正常工作,但是使用lambda的解决方案在这里工作得很好,感谢您的帮助!python文档建议在处理大型列表时使用sorted()而不是heapq.nlargest(),尽管它们没有阐明“大型列表”有多大@Matt我找不到在文档中有这样的建议——但很可能是这样的——我建议OP运行一些
timeit
测试,以找出对他的使用最有效的方法。@docs.python.org/library/heapq.html上的Lattyware如是说“后两个函数对于较小的n值表现最好。对于较大的值,使用sorted()函数更有效。此外,当n==1时,使用内置的min()和max()函数更有效。“如果你追踪重复的线索,可能会出现重复,这似乎很有希望——尽管帖子是由开发人员发布的,但事实上答案并没有透露……在你的测试中,N的值是多少?如上所述,使用heapq是有效的,因为N与len(a)相比非常小。如何修改
N
?我同意@lizzie。你能在实验中提供
N
len(a)
的值吗?如果
N
len(a)
小得多,我认为
heapq.nlargest
应该比
np.argsort
更有效。这非常有效!在我的机器上需要104毫秒(现在很忙),稍后我会再试一次,但到目前为止,这是最快的解决方案。Tnx@joshadel首先使用该函数argsort,然后返回前N个值。是否有一个Numpy/Scipy函数与Python heapq.nlagest(N,a)等效,但用于在不对整个数组进行参数排序的情况下查找前N个索引值?@dbv可能类似,但似乎只适用于最小的值。是的,对于大的
N
来说,慢速
O(N)
优于
O(N*log(N))
,这是正确的,但是
heapq
模块已经智能地实现,注意传递给
nlargest()
函数的
n
值只有在n相对较小时才会使用heap,并且当
n
明显较大且趋于列表的大小时才会切换到排序。不管怎样,从至少v2.7.11开始的最大值都将使用heap,但v3.5.2的行为与您描述的@sinister相同实际上,在v3.5.2中,仅当n大于iterable@sinister的大小时才使用sorted
heapq.nlargest(n, range(len(a)), key=a.__getitem__)