考虑下面的代码:
avgDists = np.array([1, 8, 6, 9, 4])
ids = avgDists.argsort()[:n]
这给出了n个最小元素的下标。是否可以使用相同的argsort按降序得到n个最高元素的下标?
考虑下面的代码:
avgDists = np.array([1, 8, 6, 9, 4])
ids = avgDists.argsort()[:n]
这给出了n个最小元素的下标。是否可以使用相同的argsort按降序得到n个最高元素的下标?
当前回答
正如@Kanmani所暗示的,更容易解释的实现可能使用numpy。翻转,如下所示:
import numpy as np
avgDists = np.array([1, 8, 6, 9, 4])
ids = np.flip(np.argsort(avgDists))
print(ids)
通过使用访问者模式而不是成员函数,可以更容易地读取操作的顺序。
其他回答
正如@Kanmani所暗示的,更容易解释的实现可能使用numpy。翻转,如下所示:
import numpy as np
avgDists = np.array([1, 8, 6, 9, 4])
ids = np.flip(np.argsort(avgDists))
print(ids)
通过使用访问者模式而不是成员函数,可以更容易地读取操作的顺序。
用你的例子:
avgDists = np.array([1, 8, 6, 9, 4])
获取n个最大值的索引:
ids = np.argpartition(avgDists, -n)[-n:]
按降序排序:
ids = ids[np.argsort(avgDists[ids])[::-1]]
获得结果(n=4):
>>> avgDists[ids]
array([9, 8, 6, 4])
就像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是avgdist的一个视图:
>>> ids.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
('OWNDATA'为False表示这是一个视图,而不是一个副本)
另一种方法是:
(-avgDists).argsort()[:n]
问题是这种工作方式是为数组中的每个元素创建负数:
>>> (-avgDists)
array([-1, -8, -6, -9, -4])
ANd创建一个副本来这样做:
>>> (-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
view方法基本上更快(并且使用1/2的内存…)
考虑相等元素的顺序
如果你运行一个排序程序并且两个元素相等,那么顺序通常不会改变。然而,flip/[::-1]方法改变了相等元素的顺序。
>>> arr = np.array([3, 5, 4, 7, 3])
>>>
>>> np.argsort(arr)[::-1]
array([3, 1, 2, 4, 0]) # equal elements reorderd
>>> np.argsort(-arr)
array([3, 1, 2, 0, 4]) # equal elements not reorderd (compatible to other sorting)
出于兼容性原因,我更喜欢使用负数组的argsort方法。当arr表示更复杂元素的数字表示时,这一点尤其重要。
例子:
obj = ['street', 'house', 'bridge', 'station', 'rails']
arr = np.array([3, 5, 4, 7, 3]) # cost of obj in coins
免责声明:一个更常见的方法是解决上面的例子排序(list_of_tuples_obj_cost, key=lambda x: x[1])
一种优雅的方式可以如下-
ids = np.flip(np.argsort(avgDists))
这将给出按降序排序的元素索引。 现在你可以使用常规切片…
top_n = ids[:n]