# Efficiently sorting a numpy array in descending order?

## Question:

I am surprised this specific question hasn’t been asked before, but I really didn’t find it on SO nor on the documentation of `np.sort`.

Say I have a random numpy array holding integers, e.g:

``````> temp = np.random.randint(1,10, 10)
> temp
array([2, 4, 7, 4, 2, 2, 7, 6, 4, 4])
``````

If I sort it, I get ascending order by default:

``````> np.sort(temp)
array([2, 2, 2, 4, 4, 4, 4, 6, 7, 7])
``````

but I want the solution to be sorted in descending order.

Now, I know I can always do:

``````reverse_order = np.sort(temp)[::-1]
``````

but is this last statement efficient? Doesn’t it create a copy in ascending order, and then reverses this copy to get the result in reversed order? If this is indeed the case, is there an efficient alternative? It doesn’t look like `np.sort` accepts parameters to change the sign of the comparisons in the sort operation to get things in reverse order.

`temp[::-1].sort()` sorts the array in place, whereas `np.sort(temp)[::-1]` creates a new array.

``````In : temp = np.random.randint(1,10, 10)

In : temp
Out: array([5, 2, 7, 4, 4, 2, 8, 6, 4, 4])

In : id(temp)
Out: 139962713524944

In : temp[::-1].sort()

In : temp
Out: array([8, 7, 6, 5, 4, 4, 4, 4, 2, 2])

In : id(temp)
Out: 139962713524944
``````

For short arrays I suggest using `np.argsort()` by finding the indices of the sorted negatived array, which is slightly faster than reversing the sorted array:

``````In : temp = np.random.randint(1,10, 10)

In : %timeit np.sort(temp)[::-1]
100000 loops, best of 3: 4.65 µs per loop

In : %timeit temp[np.argsort(-temp)]
100000 loops, best of 3: 3.91 µs per loop
``````

Unfortunately when you have a complex array, only `np.sort(temp)[::-1]` works properly. The two other methods mentioned here are not effective.

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

Hello I was searching for a solution to reverse sorting a two dimensional numpy array, and I couldn’t find anything that worked, but I think I have stumbled on a solution which I am uploading just in case anyone is in the same boat.

``````x=np.sort(array)
y=np.fliplr(x)
``````

`np.sort` sorts ascending which is not what you want, but the command `fliplr` flips the rows left to right! Seems to work!

Hope it helps you out!

I guess it’s similar to the suggest about `-np.sort(-a)` above but I was put off going for that by comment that it doesn’t always work. Perhaps my solution won’t always work either however I have tested it with a few arrays and seems to be OK.

i suggest using this …

``````np.arange(start_index, end_index, intervals)[::-1]
``````

for example:

``````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. ]
``````

# Be careful with dimensions.

### Let

``````x  # initial numpy array
I = np.argsort(x) or I = x.argsort()
y = np.sort(x)    or y = x.sort()
z  # reverse sorted array
``````

### Full Reverse

``````z = x[I[::-1]]
z = -np.sort(-x)
z = np.flip(y)
``````

### First Dimension Reversed

``````z = y[::-1]
z = np.flipud(y)
z = np.flip(y, axis=0)
``````

### Second Dimension Reversed

``````z = y[::-1, :]
z = np.fliplr(y)
z = np.flip(y, axis=1)
``````

# Testing

Testing on a 100×10×10 array 1000 times.

``````Method       | Time (ms)
-------------+----------
y[::-1]      | 0.126659  # only in first dimension
-np.sort(-x) | 0.133152
np.flip(y)   | 0.121711
x[I[::-1]]   | 4.611778

x.sort()     | 0.024961
x.argsort()  | 0.041830
np.flip(x)   | 0.002026
``````

This is mainly due to reindexing rather than `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()[::-1]], xs)
timeit(lambda x: x.sort(), xs)
timeit(lambda x: x.argsort(), xs)
timeit(lambda x: np.flip(x), xs)
``````

You could sort the array first (Ascending by default) and then apply np.flip()
(https://docs.scipy.org/doc/numpy/reference/generated/numpy.flip.html)

FYI It works with datetime objects as well.

Example:

``````    x = np.array([2,3,1,0])
x_sort_asc=np.sort(x)
print(x_sort_asc)

>>> array([0, 1, 2, 3])

x_sort_desc=np.flip(x_sort_asc)
print(x_sort_desc)

>>> array([3,2,1,0])
``````

Here is a quick trick

``````In: import numpy as np
In: temp = np.random.randint(1,10, 10)
In: temp
Out: array([5, 4, 2, 9, 2, 3, 4, 7, 5, 8])

In: sorted = np.sort(temp)
In: rsorted = list(reversed(sorted))
In: sorted
Out: array([2, 2, 3, 4, 4, 5, 5, 7, 8, 9])

In: rsorted
Out: [9, 8, 7, 5, 5, 4, 4, 3, 2, 2]
``````

`np.flip()` and reversed indexed are basically the same. Below is a benchmark using three different methods. It seems `np.flip()` is slightly faster. Using negation is slower because it is used twice so reversing the array is faster than that.

** Note that `np.flip()` is faster than `np.fliplr()` according to my tests.

``````def sort_reverse(x):
return np.sort(x)[::-1]

def sort_negative(x):
return -np.sort(-x)

def sort_flip(x):
return np.flip(np.sort(x))

arr=np.random.randint(1,10000,size=(1,100000))

%timeit sort_reverse(arr)
%timeit sort_negative(arr)
%timeit sort_flip(arr)
``````

and the results are:

``````6.61 ms ± 67.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
6.69 ms ± 64.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
6.57 ms ± 58.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
``````
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.