Ranking, top-k, binning and deduplication are everyday tasks with fast dedicated NumPy routines.
np.sort(a) returns a sorted copy; a.sort() sorts in place. Both sort along the last axis by default; pass axis=0 to sort each column, or axis=None to flatten first. NaNs are sorted to the end. There is no reverse flag: use np.sort(a)[::-1] for descending order.
`np.argsort(a)` returns the indices that would sort a. That is the tool for sorting one array by another (names[np.argsort(scores)]) and for ranking. Use kind="stable" when ties must keep their original order, for example when sorting by a secondary key after a primary one. np.lexsort sorts by several keys at once.
For the top or bottom k values you don't need a full sort. np.partition(a, k) rearranges so that the element at position k is where it would be in sorted order, smaller ones before it and larger ones after, in O(n) time. np.argpartition gives the indices.
`np.searchsorted(sorted_arr, values)` does a binary search: for each value it returns the index where it would be inserted to keep the order. It's how you bin values into intervals or look up many keys in a sorted table in O(log n) each.
`np.unique(a)` returns the sorted distinct values; with return_counts=True or return_inverse=True it also gives frequencies or a mapping from each element to its unique value. NumPy 2 adds the clearer np.unique_values, np.unique_counts and np.unique_inverse, returning named tuples.
Also handy: np.argmax/np.argmin for positions of extremes, np.nonzero for positions of matches, and np.isin(a, values) for vectorized membership tests.
Example
import numpy as np
scores = np.array([72, 95, 61, 88, 95])
names = np.array(["ann", "bo", "cy", "di", "ed"])
order = np.argsort(-scores, kind="stable") # descending, ties stable
print(names[order]) # ['bo' 'ed' 'di' 'ann' 'cy']
top2 = np.argpartition(scores, -2)[-2:] # top 2, unordered
print(np.sort(names[top2])) # ['bo' 'ed']
edges = np.array([60, 70, 80, 90]) # grade boundaries
print(np.searchsorted(edges, scores, side="right")) # [2 4 1 3 4]
vals, counts = np.unique(scores, return_counts=True)
print(vals, counts) # [61 72 88 95] [1 1 1 2]
res = np.unique_counts(scores)
print(res.values, res.counts)
print(np.isin(names, ["bo", "zz"])) # [False True False False False]Remember
np.sortcopies,a.sort()is in place; reverse with[::-1]argsortgives ordering indices; usekind='stable'when ties matterpartition/argpartitionfind top-k in linear timesearchsortedbinary-searches a sorted array;uniquededuplicates and counts
Watch out for
- Using
searchsortedon an unsorted array: it won't complain, but the answers are wrong.