可以按降序使用argsort吗?

问题描述

如果对数组求反,则最低的元素变为最高的元素,反之亦然。因此,n最高元素的索引是:

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

评论中所述,对此进行推理的另一种方法是观察大元素在argsort中排在最后 。因此,您可以从argsort的末尾读取以找到n最高的元素:

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

这两种方法的时间复杂度均为 O(n log n) ,因为在此argsort调用是主要项。但是第二种方法有一个很好的优点:它将数组的 O(n) 取反替换为 O(1) 切片。如果在循环中使用小型数组,则避免这种求反可能会获得一些性能提升;如果使用大型数组,则可以节省内存使用量,因为这种否定会创建整个数组的副本。

请注意,这些方法并不总是给出相等的结果:如果要求稳定的排序实现(argsort例如,通过传递关键字parameter)kind='mergesort',则第一个策略将保留排序稳定性,但是第二个策略将破坏稳定性(即,位置相等)项目将被撤消)。

使用100个浮点和30个尾巴的小阵列,视图方法的速度提高了约15%

>>> avgDists = np.random.rand(100)
>>> n = 30
>>> timeit (-avgDists).argsort()[:n]
1.93 µs ± 6.68 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> timeit avgDists.argsort()[::-1][:n]
1.64 µs ± 3.39 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> timeit avgDists.argsort()[-n:][::-1]
1.64 µs ± 3.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

对于较大的阵列,argsort占主导地位,并且没有明显的时序差异

>>> avgDists = np.random.rand(1000)
>>> n = 300
>>> timeit (-avgDists).argsort()[:n]
21.9 µs ± 51.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> timeit avgDists.argsort()[::-1][:n]
21.7 µs ± 33.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> timeit avgDists.argsort()[-n:][::-1]
21.9 µs ± 37.1 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

请注意,以下来自nedim的评论不正确。在反转之前或之后进行截断在效率上没有区别,因为这两个操作都只是以不同的方式跨越阵列视图,而实际上并未复制数据。

解决方法

考虑以下代码:

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

这给了我n最小元素的索引。是否可以argsort按降序使用它来获得n最高元素的索引?

猜你在找的技术问答相关文章

如何检查配对的蓝牙设备是打印机还是扫描仪(Android)
是否允许实体正文进行HTTP DELETE请求?
如何将ZipInputStream转换为InputStream?
java.util.logging Java 8中的变量
PowerMockito.doReturn返回null
Java中的RESTful调用
Swing / Java:如何正确使用getText和setText字符串
特殊字符和重音字符
Android Studio中的ndk.dir错误
错误“找不到主类”