是否可以按降序使用argsort

考虑下面的代码:

avgDists = np.array([1, 8, 6, 9, 4]) ids = avgDists.argsort()[:n] 

这给了我n最小元素的索引。 是否有可能使用这个相同的argsort降序获得n最高元素的指数?

如果你否定一个数组,最低的元素成为最高的元素,反之亦然。 因此, n最高要素的指标是:

 (-avgDists).argsort()[:n] 

正如评论中提到的那样,另一种推理的方法是观察这些大元素是否会在最后的时候出现。 所以,你可以从尾巴中读取最高的元素:

 avgDists.argsort()[::-1][:n] 

这两种方法的时间复杂度都是O(n log n) ,因为在这里argsort调用是占主导地位的。 但第二种方法有一个很好的优点:它用一个O(1)片代替O(n)数组的否定。 如果你正在处理循环内的小数组,那么你可以通过避免这个否定获得一些性能上的提升,如果你正在处理巨大的数组,那么你可以节省内存使用,因为否定会创build整个数组的副本。

注意,这些方法并不总是给出相同的结果:如果一个稳定的sorting实现被要求argsort ,例如通过传递关键字参数kind='mergesort' ,那么第一个策略将保持sorting的稳定性,但第二个策略将打破稳定(即相同项目的位置将被颠倒)。

就像Python一样, [::-1]反转了argsort()[:n]返回的数组给出的最后n个元素:

 >>> avgDists=np.array([1, 8, 6, 9, 4]) >>> n=3 >>> ids = avgDists.argsort()[::-1][:n] >>> ids array([3, 1, 2]) 

这种方法的优点是ids是avgDists的一个视图 :

 >>> ids.flags C_CONTIGUOUS : False F_CONTIGUOUS : False OWNDATA : False WRITEABLE : True ALIGNED : True UPDATEIFCOPY : False 

('OWNDATA'为False表示这是一个视图,而不是副本)

另一种方法是这样的:

 (-avgDists).argsort()[:n] 

问题是这样做的方式是创build数组中的每个元素的负数:

 >>> (-avgDists) array([-1, -8, -6, -9, -4]) 

ANd创build一个副本来这样做:

 >>> (-avgDists_n).flags['OWNDATA'] True 

所以,如果你每一个时间,即使这个非常小的数据集:

 >>> import timeit >>> timeit.timeit('(-avgDists).argsort()[:3]', setup="from __main__ import avgDists") 4.2879798610229045 >>> timeit.timeit('avgDists.argsort()[::-1][:3]', setup="from __main__ import avgDists") 2.8372560259886086 

视图方法快得多

您可以创build数组的副本,然后将每个元素与-1相乘。
作为一个效果,以前最大的元素将成为最小的。
副本中n个最小元素的个数是原始元素中最重要的元素。

您可以使用flip命令numpy.flipud()numpy.fliplr()在使用argsort命令sorting后按降序获取索引。 那是我通常做的。

您可以使用np.argpartition而不是使用np.argpartition – 如果您只需要最低/最高n个元素的索引。

这不需要sorting整个数组,但只需要你需要的部分,但要注意的是“你的分区内的顺序”是未定义的,所以虽然它给出正确的指数,他们可能不正确的顺序:

 >>> avgDists = [1, 8, 6, 9, 4] >>> np.array(avgDists).argpartition(2)[:2] # indices of lowest 2 items array([0, 4], dtype=int64) >>> np.array(avgDists).argpartition(-2)[-2:] # indices of highest 2 items array([1, 3], dtype=int64) 

另一种方法是在argsort的参数中只使用一个' – ',如:“df [np.argsort(-df [:, 0])]”,如果df是数据框,并且您想按照第一个列(由列号“0”表示)。 根据需要更改列名称。 当然,这个列必须是数字的。

用你的例子:

 avgDists = np.array([1, 8, 6, 9, 4]) 

获取n个最大值的索引:

 ids = np.argpartition(avgDists, -n)[-n:] 

按降序对它们进行sorting:

 ids = ids[np.argsort(avgDists[ids])[::-1]] 

获得结果(n = 4):

 >>> avgDists[ids] array([9, 8, 6, 4])