Можно ли использовать argsort в порядке убывания


рассмотрим следующий код:

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

это дает мне показатели n мельчайшие элементы. Можно ли использовать этот же argsort в порядке убывания, чтобы получить индексы n высокие элементы ?

7 103

7 ответов:

если вы отрицаете массив, самые низкие элементы становятся самыми высокими элементами и наоборот. Таким образом, индексы n высшие элементы:

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

еще один способ рассуждать об этом, как уже упоминалось в комментарии, это наблюдать, что большие элементы приходят последние в argsort. Итак, вы можете прочитать из хвоста argsort, чтобы найти n высшие элементы:

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

оба метода O(n log n) во времени сложности, потому что argsort вызов является доминирующим термином здесь. Но второй подход имеет хорошее преимущество: он заменяет O (n) отрицание массива с помощью O (1) срез. Если вы работаете с небольшими массивами внутри циклов, то вы можете получить некоторый прирост производительности, избегая этого отрицания, и если вы работаете с огромными массивами, то вы можете сэкономить на использовании памяти, потому что отрицание создает копию всего массива.

обратите внимание, что эти методы не всегда дают эквивалентные результаты: если требуется стабильная реализация сортировки argsort, например, передавая аргумент ключевого слова kind='mergesort', то первая стратегия сохранит стабильность сортировки, но вторая стратегия нарушит стабильность (т. е. позиции равных элементов будут перевернуты).

так же, как 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]

проблема в том, что способ, которым это работает, заключается в создании негатива каждого элемент в массиве:

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

и создает копию для этого:

>>> (-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

метод просмотра существенно быстрее

вы можете создать копию массива, а затем умножить каждый элемент с -1.
В результате раньше самые большие элементы стали бы самыми маленькими.
Индексами n наименьших элементов в копии являются n наибольших элементов в оригинале.

вы можете использовать флип команды numpy.flipud() или numpy.fliplr() чтобы получить индексы, в порядке убывания после сортировки с помощью . Это то, что я обычно делаю.

вместо np.argsort вы могли бы использовать np.argpartition - если вам нужны только индексы самых низких / самых высоких n элементов.

это не требует сортировки всего массива, но только часть, которая вам нужна, но обратите внимание, что" порядок внутри вашего раздела " не определен, поэтому, хотя он дает правильные индексы, они могут быть неправильно упорядочены:

>>> 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)

С вас пример:

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])

другой способ-использовать только '-' в аргументе для argsort, как в : "df[np.argsort (- df[:, 0])]", при условии, что DF является фреймом данных, и вы хотите отсортировать его по первому столбцу (представленному номером столбца '0'). Измените имя столбца соответствующим образом. Конечно, столбец должен быть числовым.