Skip to main content

Python NumPy: How to Use argsort Indices for Descending Order

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

# Default argsort (ascending)
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])

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

# Argsort the negated array (ascending sort of negative values)
descending_indices_negation = np.argsort(negated_array)
# Or more concisely: descending_indices_negation = (-original_array).argsort()

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

Important: Ensure the expression (-original_array) is enclosed in parentheses if using it directly as (-original_array).argsort() to ensure negation happens before the method call, although np.argsort(-original_array) also works. This method only works for numeric types where negation inverts the order.

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

# Step 1: Get indices for ascending sort
ascending_indices = np.argsort(original_array)

# Step 2: Reverse the array of ascending indices
descending_indices_slice = ascending_indices[::-1]
# Or concisely: descending_indices_slice = np.argsort(original_array)[::-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]
note

The slice [::-1] creates a reversed view (or copy, depending on context) of the ascending_indices array. This method is quite Pythonic and generally efficient.

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

# Step 1: Get indices for ascending sort
ascending_indices = np.argsort(original_array)

# Step 2: Reverse the array of ascending indices using np.flip()
descending_indices_flip = np.flip(ascending_indices)
# Or concisely: descending_indices_flip = np.flip(np.argsort(original_array))

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

np.flip() is often slightly more explicit than [::-1] for reversal, especially for multi-dimensional arrays where you might specify an axis.

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

# Argsort the multiplied array
descending_indices_multiply = np.argsort(multiplied_array)
# Or concisely: descending_indices_multiply = (original_array * -1).argsort()

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

This is functionally identical to Method 1 for numeric arrays. Method 1 ((-arr).argsort()) is slightly more common and perhaps a hair more direct than (arr * -1).argsort().

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

# Using negation method for descending indices
descending_indices = (-original_array).argsort()

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

# Slice the first N indices from the descending_indices array
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.