Skip to content

Python NumPy: How to Use "argsort" Indices for Descending Order

Learn how to generate descending order indices with NumPy's argsort() using negation, array reversal, or np.flip() for efficient sorting of numeric arrays.

The numpy.argsort() function is a powerful tool in NumPy for finding the indices that would sort an array. By default, it returns indices for an ascending sort. However, a common requirement is to get the indices that would sort an array in descending order, for example, to find the indices of the largest N elements or to process data from largest to smallest.

This guide will comprehensively demonstrate several effective methods to achieve a descending order argsort in NumPy. We'll cover techniques such as negating the array before sorting, using slice reversal [::-1], leveraging numpy.flip(), and multiplying the array by -1, explaining the logic behind each approach.

Understanding numpy.argsort() (Ascending Order by Default)

numpy.argsort(a, axis=-1, kind=None, order=None) returns an array of indices of the same shape as a that would sort a along the specified axis. By default, the sort is ascending.

import numpy as np

original_array = np.array([10, 50, 5, 80, 25])
print(f"Original array: {original_array}")

ascending_indices = np.argsort(original_array)
print(f"Indices for ascending sort: {ascending_indices}")
print(f"Array sorted ascending: {original_array[ascending_indices]}")

Output:

Original array: [10 50  5 80 25]
Indices for ascending sort: [2 0 4 1 3]
Array sorted ascending: [5 10 25 50 80]

Our goal is to get indices like [3, 1, 4, 0, 2] which would sort original_array in descending order.

For numeric arrays, the simplest and often most intuitive way to get descending argsort indices is to sort the negation of the array in ascending order. When you negate an array, the smallest elements become the largest (in terms of their new negative value being most negative) and vice versa.

import numpy as np

original_array = np.array([10, 50, 5, 80, 25])

negated_array = -original_array
print(f"Negated array: {negated_array}")

descending_indices_negation = np.argsort(negated_array)

print(f"Indices for descending sort (by negating): {descending_indices_negation}")
print(f"Array sorted descending: {original_array[descending_indices_negation]}")

Output:

Negated array: [-10 -50  -5 -80 -25]
Indices for descending sort (by negating): [3 1 4 0 2]
Array sorted descending: [80 50 25 10  5]

Method 2: Reversing Ascending argsort() Indices with Slice [::-1]

This method first gets the indices for an ascending sort and then reverses that array of indices using slice notation [::-1].

import numpy as np

original_array = np.array([10, 50, 5, 80, 25])

ascending_indices = np.argsort(original_array)

descending_indices_slice = ascending_indices[::-1]

print(f"Indices for descending sort (using slice [::-1]): {descending_indices_slice}")
print(f"Array sorted descending: {original_array[descending_indices_slice]}")

Output:

Indices for descending sort (using slice [::-1]): [3 1 4 0 2]
Array sorted descending: [80 50 25 10  5]

Method 3: Reversing Ascending argsort() Indices with numpy.flip()

Similar to slice reversal, numpy.flip(arr, axis=None) reverses the order of elements in an array along the given axis (or all axes if axis=None). For a 1D array of indices, it effectively reverses it.

import numpy as np

original_array = np.array([10, 50, 5, 80, 25])

ascending_indices = np.argsort(original_array)

descending_indices_flip = np.flip(ascending_indices)

print(f"Indices for descending sort (using np.flip()): {descending_indices_flip}")
print(f"Array sorted descending: {original_array[descending_indices_flip]}")

Output:

Indices for descending sort (using np.flip()): [3 1 4 0 2]
Array sorted descending: [80 50 25 10  5]

Method 4: Multiplying the Array by -1 Before argsort() (Similar to Negation)

Multiplying a numeric array by -1 has the same effect as negating it with the unary minus operator (-array). This method also relies on inverting the order by changing the signs of the numbers.

import numpy as np

original_array = np.array([10, 50, 5, 80, 25])

multiplied_array = original_array * -1
print(f"Array multiplied by -1: {multiplied_array}")

descending_indices_multiply = np.argsort(multiplied_array)

print(f"Indices for descending sort (by multiplying by -1): {descending_indices_multiply}")
print(f"Array sorted descending: {original_array[descending_indices_multiply]}")

Output:

Array multiplied by -1: [-10 -50  -5 -80 -25]
Indices for descending sort (by multiplying by -1): [3 1 4 0 2]
Array sorted descending: [80 50 25 10  5]

Selecting Indices of the Top N Largest Elements

Once you have the indices for a descending sort, you can easily get the indices of the top N largest elements by slicing the resulting index array.

import numpy as np

original_array = np.array([10, 50, 5, 80, 25, 90, 15]) # Added more elements

descending_indices = (-original_array).argsort()

N = 3 # We want indices of the top 3 largest elements

indices_of_top_N = descending_indices[:N]

print(f"Original array: {original_array}")
print(f"All indices for descending sort: {descending_indices}")
print(f"Indices of the top {N} largest elements: {indices_of_top_N}")
print(f"The top {N} largest elements themselves: {original_array[indices_of_top_N]}")

Output:

Original array: [10 50  5 80 25 90 15]
All indices for descending sort: [5 3 1 4 6 0 2]
Indices of the top 3 largest elements: [5 3 1]
The top 3 largest elements themselves: [90 80 50]

Choosing the Best Method

  • Negating the array ((-arr).argsort()): This is very common, clear, and efficient for numeric arrays. It directly reflects the idea of sorting by "largest first" by making largest positive numbers the "smallest" negative numbers.
  • Slicing [::-1] or np.flip(): These are generally applicable to any array of indices returned by argsort() regardless of the original array's dtype (as long as argsort itself is meaningful for that dtype). They are good general-purpose ways to reverse an ordered set of indices. Performance differences between [::-1] and np.flip() on 1D arrays are usually negligible.
  • Multiplying by -1: Functionally the same as negating for numeric arrays, but slightly more verbose.

For numeric data, negating is often the most direct. For a general way to reverse any argsort result, [::-1] is very Pythonic.

Conclusion

While numpy.argsort() defaults to providing indices for an ascending sort, you can easily obtain indices for a descending sort using several techniques:

  1. Negate the numeric array before calling argsort(): (-my_array).argsort().
  2. Perform an ascending argsort() and then reverse the resulting index array using slice notation [::-1]: my_array.argsort()[::-1].
  3. Perform an ascending argsort() and then reverse the index array using np.flip(): np.flip(my_array.argsort()).

These methods allow you to effectively find the order of elements from largest to smallest, which is crucial for tasks like identifying top N values, ranking, or custom sorting procedures in NumPy.

Navigation