Эффективно сортировать массив numpy в порядке убывания?
Я удивлен, что этот конкретный вопрос не задавался раньше, но я действительно не нашел его на SO или документации np.sort
.
Скажем, у меня есть случайный массив numpy, содержащий целые числа, например:
> temp = np.random.randint(1,10, 10)
> temp
array([2, 4, 7, 4, 2, 2, 7, 6, 4, 4])
Если я его сортирую, по умолчанию получаю по возрастанию:
> np.sort(temp)
array([2, 2, 2, 4, 4, 4, 4, 6, 7, 7])
но я хочу, чтобы решение сортировалось в порядке убывания.
Теперь я знаю, что всегда могу:
reverse_order = np.sort(temp)[::-1]
но является ли это последним оператором эффективным? Разве он не создает копию в порядке возрастания, а затем отменяет эту копию, чтобы получить результат в обратном порядке? Если это действительно так, есть ли эффективная альтернатива? Это не похоже, что np.sort
принимает параметры для изменения знака сравнений в операции сортировки, чтобы получить вещи в обратном порядке.
Ответы
Ответ 1
temp[::-1].sort()
сортирует массив на месте, тогда как np.sort(temp)[::-1]
создает новый массив.
In [25]: temp = np.random.randint(1,10, 10)
In [26]: temp
Out[26]: array([5, 2, 7, 4, 4, 2, 8, 6, 4, 4])
In [27]: id(temp)
Out[27]: 139962713524944
In [28]: temp[::-1].sort()
In [29]: temp
Out[29]: array([8, 7, 6, 5, 4, 4, 4, 4, 2, 2])
In [30]: id(temp)
Out[30]: 139962713524944
Ответ 2
>>> a=np.array([5, 2, 7, 4, 4, 2, 8, 6, 4, 4])
>>> np.sort(a)
array([2, 2, 4, 4, 4, 4, 5, 6, 7, 8])
>>> -np.sort(-a)
array([8, 7, 6, 5, 4, 4, 4, 4, 2, 2])
Ответ 3
Для коротких массивов я предлагаю использовать np.argsort()
путем поиска индексов отсортированного отрицательного массива, который немного быстрее, чем реверсирование отсортированного массива:
In [37]: temp = np.random.randint(1,10, 10)
In [38]: %timeit np.sort(temp)[::-1]
100000 loops, best of 3: 4.65 µs per loop
In [39]: %timeit temp[np.argsort(-temp)]
100000 loops, best of 3: 3.91 µs per loop
Ответ 4
К сожалению, когда у вас сложный массив, работает только np.sort(temp)[::-1]
. Два других метода, упомянутых здесь, неэффективны.
Ответ 5
Здравствуйте! Я искал решение для обратной сортировки двумерного массива numpy, и я не смог найти ничего, что сработало, но я думаю, что наткнулся на решение, которое я загружаю на тот случай, если кто-нибудь окажется в одной лодке.
x=np.sort(array)
y=np.fliplr(x)
np.sort сортирует по возрастанию, что не то, что вам нужно, но команда fliplr переворачивает строки слева направо! Кажется, работает!
Надеюсь, это поможет вам!
Я предполагаю, что это похоже на предложение о -np.sort(-a) выше, но я был отстранен от комментариев, что это не всегда работает. Возможно, мое решение не всегда будет работать, однако я проверил его с несколькими массивами и, похоже, все в порядке.
Ответ 6
Я предлагаю использовать это...
np.arange(start_index, end_index, intervals)[::-1]
например:
np.arange(10, 20, 0.5)
np.arange(10, 20, 0.5)[::-1]
Тогда ваш результат:
[ 19.5, 19. , 18.5, 18. , 17.5, 17. , 16.5, 16. , 15.5,
15. , 14.5, 14. , 13.5, 13. , 12.5, 12. , 11.5, 11. ,
10.5, 10. ]
Ответ 7
Будьте осторожны с размерами.
Пусть
x # initial numpy array
I = np.argsort(x) or I = x.argsort()
y = np.sort(x) or y = x.sort()
z # reverse sorted array
Полный реверс
z = x[-I]
z = -np.sort(-x)
z = np.flip(y)
flip
изменено в 1.15
, в предыдущих версиях 1.14
требовалось axis
. Решение: pip install --upgrade numpy
.
Первое измерение перевернуто
z = y[::-1]
z = np.flipud(y)
z = np.flip(y, axis=0)
Второе измерение перевернуто
z = y[::-1, :]
z = np.fliplr(y)
z = np.flip(y, axis=1)
Тестирование
Тестирование на массиве 100 × 10 × 10 раз 1000 раз.
Method | Time (ms)
-------------+----------
y[::-1] | 0.126659 # only in first dimension
-np.sort(-x) | 0.133152
np.flip(y) | 0.121711
x[-I] | 4.611778
x.sort() | 0.024961
x.argsort() | 0.041830
np.flip(x) | 0.002026
Это в основном из-за переиндексации, а не argsort
.
# Timing code
import time
import numpy as np
def timeit(fun, xs):
t = time.time()
for i in range(len(xs)): # inline and map gave much worse results for x[-I], 5*t
fun(xs[i])
t = time.time() - t
print(np.round(t,6))
I, N = 1000, (100, 10, 10)
xs = np.random.rand(I,*N)
timeit(lambda x: np.sort(x)[::-1], xs)
timeit(lambda x: -np.sort(-x), xs)
timeit(lambda x: np.flip(x.sort()), xs)
timeit(lambda x: x[-x.argsort()], xs)
timeit(lambda x: x.sort(), xs)
timeit(lambda x: x.argsort(), xs)
timeit(lambda x: np.flip(x), xs)