Если вы отрицаете массив, самые низкие элементы становятся самыми высокими элементами и наоборот. Поэтому индексами n
высших элементов являются:
(-avgDists).argsort()[:n]
Другой способ рассуждать об этом, как упомянуто в комментариях , состоит в том , чтобы наблюдать, что большие элементы идут последними в argsort. Итак, вы можете прочитать из хвоста argsort, чтобы найти самые n
высокие элементы:
avgDists.argsort()[::-1][:n]
Оба метода имеют O (n log n) во временной сложности, потому что argsort
здесь преобладает вызов. Но у второго подхода есть приятное преимущество: он заменяет отрицание O (n) массива на срез O (1) . Если вы работаете с маленькими массивами внутри циклов, вы можете получить некоторое повышение производительности, избегая этого отрицания, а если вы работаете с огромными массивами, то вы можете сэкономить на использовании памяти, поскольку отрицание создает копию всего массива.
Обратите внимание, что эти методы не всегда дают эквивалентные результаты: если запрашивается стабильная реализация сортировки argsort
, например, путем передачи аргумента ключевого слова 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)
Обратите внимание, что комментарий от Недима ниже является неправильным. Обрезание до или после реверса не влияет на эффективность, так как обе эти операции только по-разному оценивают массив и не копируют данные.
ids = np.array(avgDists).argsort()[-n:]
?