Written and maintained by CASRAI Editorial Board
Last updated
numpy.argsort() returns the indices that would sort an array, not the sorted values themselves. Those indices let you sort one array by another, pick the top-k records, or rank observations without moving the data. This guide covers the signature, descending order on every NumPy version, and how to apply the returned indices correctly in two or more dimensions.
What argsort is used for in research
Sorting values loses the link between each value and its original position. np.argsort keeps that link. Typical research uses, all of which follow directly from the definition (“returns the indices that would sort an array”):
- Sort one array by another. If
scoresholds a measurement per sample andnamesholds the sample labels,names[np.argsort(scores)]lists the labels in score order. - Select the top-k or bottom-k records. Slice the index array instead of sorting the whole dataset again.
- Rank observations. The positions in the index array order the data; for tie-aware ranks see the alternatives table below.
If your arrays contain missing values, read the companion guide on detecting, ignoring and replacing NaN in NumPy first, because sorting treats NaN in a fixed way (see Troubleshooting).
Install or access
NumPy is installed from the official install page at numpy.org/install. The two documented routes are:
- pip:
pip install numpy - conda:
conda create -n my-env, thenconda activate my-env, thenconda install numpy
To keep a project isolated with a virtual environment, the same page lists python -m venv my-env, activation with source my-env/bin/activate (macOS and Linux) or my-env\Scripts\activate (Windows), and then pip install numpy. For a refresher on creating arrays, see creating a NumPy array from a list and reading its shape.
Step-by-step: using np.argsort
The signature
From the current NumPy reference:
numpy.argsort(a, axis=-1, kind=None, order=None, *, stable=None, descending=<no value>)
axis: the axis to sort along. The default is-1, the last axis. Withaxis=Nonethe array is flattened first.kind: one of'quicksort'(the default),'mergesort','heapsort'or'stable'.order: for arrays with named fields, the fields to compare first; unspecified fields break ties in dtype order.stable: if True, equal values keep their original relative order. Added in NumPy 2.0.0.descending: if True, the indices sort in descending order. Added in NumPy 2.5.0.
1. Sort a 1-D array
- Import NumPy and build an array:
import numpy as npthenx = np.array([3, 1, 2]). - Call
np.argsort(x). The documented result isarray([1, 2, 0]): the smallest value sits at index 1, the next at index 2, the largest at index 0. - Apply the indices with
x[np.argsort(x)]to get the sorted values.
2. Sort along an axis of a 2-D array
With x = np.array([[0, 3], [2, 2]]) the reference shows:
np.argsort(x, axis=0)givesarray([[0, 1], [1, 0]])(sorts down each column).np.argsort(x, axis=1)givesarray([[0, 1], [0, 1]])(sorts across each row).
3. Sort a flattened array and recover 2-D positions
Passing axis=None sorts the flattened array. To turn the flat indices back into row and column positions, use np.unravel_index:
ind = np.unravel_index(np.argsort(x, axis=None), x.shape)
# (array([0, 1, 1, 0]), array([0, 0, 1, 1]))
x[ind]
# array([0, 2, 2, 3])
4. Descending order, on any NumPy version
This is where most tutorials stop at one idiom, and the right choice depends on your NumPy version.
- NumPy 2.5.0 or newer:
np.argsort(x, descending=True). Forx = np.array([3, 1, 2])this gives indices[0, 2, 1]. The reference states that NaN values are placed at the end for both orders. - Older versions: the
descendingkeyword does not exist. Reverse the ascending result withnp.argsort(x)[::-1], which also gives[0, 2, 1]for the same array.
Reversing has a side effect on ties. Because the reversed list flips the order of equal values, their original relative order is lost. For numeric (signed) arrays, np.argsort(-x, kind='stable') keeps tied values in their original order while sorting descending. For x = np.array([1, 2, 1]) this returns [1, 0, 2], whereas np.argsort(x)[::-1] on the stable ascending order [0, 2, 1] returns [1, 2, 0]. Negating is not safe for unsigned integer types, so use the descending keyword there if your version has it.
5. Top-k and bottom-k
For the k largest values, slice the end of the ascending index array: np.argsort(x)[-2:] on [3, 1, 2] gives [2, 0], the positions of the values 2 and 3. For the k smallest, use np.argsort(x)[:k].
6. Sort by several keys with a structured array
For an array with named fields, order sets key priority. The reference example uses x = np.array([(1, 0), (0, 1)], dtype=[('x', '<i4'), ('y', '<i4')]):
np.argsort(x, order=('x', 'y'))givesarray([1, 0])np.argsort(x, order=('y', 'x'))givesarray([0, 1])
The same two keys in the opposite order produce opposite results, so the first name listed is the primary key.
Output and how to read it
The result is an integer array with the same shape as the input along the sorted axis. Reading it correctly depends on dimensions:
- 1-D:
a[index_array]returns the sorted array. - Any dimension: the reference gives the general rule as
np.take_along_axis(a, index_array, axis=axis). For example,ind = np.argsort(x, axis=1)followed bynp.take_along_axis(x, ind, axis=1)equalsnp.sort(x, axis=1). - Flattened (
axis=None): usenp.unravel_indexas in step 3.
Writing x[np.argsort(x, axis=1)] on a 2-D array does not sort each row. It indexes whole rows by the values in the index array and returns a 3-D result, so use take_along_axis instead.
Choosing a sort algorithm (kind)
The NumPy sort reference lists these properties for the algorithms that kind selects:
| kind | Relative speed | Worst case | Work space | Stable |
|---|---|---|---|---|
| quicksort | 1 | O(n^2) | 0 | No |
| heapsort | 3 | O(n*log(n)) | 0 | No |
| mergesort | 2 | O(n*log(n)) | about n/2 | Yes |
| timsort | 2 | O(n*log(n)) | about n/2 | Yes |
The same page describes the default quicksort as an introsort that switches to heapsort when partitioning stalls, so its worst case in practice is O(n*log(n)). In argsort, 'stable' and 'mergesort' both use timsort under the covers, and 'mergesort' is kept for backwards compatibility. Choose a stable kind whenever tied values must keep their original order, for example when a second sort or a report depends on it.
Troubleshooting
NaN values appear at the end
Since NumPy 1.4.0, argsort works with real and complex arrays that contain NaN, and the NaN positions come last. The reference states this holds for descending order too, so a descending sort does not put NaN first.
Tied values come out in an unexpected order
The default quicksort is not stable. Pass kind='stable' (or stable=True on NumPy 2.0.0 or newer) to keep equal values in their original order.
2-D indexing gives the wrong shape
Use np.take_along_axis with the same axis, as described above.
The descending keyword is not recognised
That parameter was added in NumPy 2.5.0. Reverse the ascending result instead, as in step 4, or upgrade NumPy. Related array-shaping behaviour is covered in the guides on np.clip bounds and np.repeat axis and counts.
Free alternatives
All four are free, open-source tools documented on their official sites.
| Tool | What it returns | Use it when | Documented behaviour |
|---|---|---|---|
numpy.sort |
The sorted values | You do not need the original positions | NaN values sort to the end (NumPy 1.4.0 and newer) |
numpy.lexsort(keys, axis=-1) |
Indices from an indirect stable sort on several keys | You have several separate arrays as keys | The last key is the primary sort key; ties are broken by the second-to-last key, and so on |
pandas.Series.sort_values |
A sorted Series | Your data already lives in pandas | Default ascending=True and na_position='last'; ascending=False sorts descending; mergesort and stable are the stable options |
scipy.stats.rankdata |
Ranks, beginning at 1 | You need ranks with defined tie handling rather than indices | Tie method is one of average (default), min, max, dense, ordinal; nan_policy is propagate, omit or raise |
For statistical modelling in Python after the sorting step, see ANOVA in Python with statsmodels.
FAQ
What does np.argsort return?
An integer array of indices that would sort the input. For np.array([3, 1, 2]) it returns array([1, 2, 0]).
How do I sort in descending order with np.argsort?
On NumPy 2.5.0 or newer, pass descending=True. On older versions, reverse the ascending result with [::-1], or use np.argsort(-x, kind='stable') for signed numeric data when ties must keep their original order.
How do I get the sorted array from the indices?
For 1-D input, a[index_array]. For any dimension, np.take_along_axis(a, index_array, axis=axis).
How do I sort a 2-D array by column or by row?
Use axis=0 to sort down columns and axis=1 to sort across rows, then apply the result with np.take_along_axis.
Is np.argsort stable?
Not by default. Use kind='stable', or stable=True on NumPy 2.0.0 and newer.
Where do NaN values go?
To the end of the result, in both ascending and descending order.
Sources
Date checked: 2026-10-29.








