NumPy·Lesson 17·11 min·0/4 exercises

Sorting and searching

argsort is the one that matters — it returns the order, so you can apply it anywhere.

np.sortnp.argsortnp.argpartitionnp.searchsortednp.argmaxnp.digitize

Watch it happen

Play it through, or step back and forth yourself.

namescore
Asha72
Bilal45
Chen90
Dev58
scores
0
1
2
3
72
45
90
58
shape (4,)
np.sort(scores)
np.sort(scores)
0
1
2
3
45
58
72
90
shape (4,)

np.sort(scores) returns a sorted copy, ascending. scores.sort() — the method — sorts in place and returns None, which catches people out about once each.

The idea

np.sort(x) returns a sorted copy, ascending. x.sort() — the method — sorts in place and returns None, which everyone assigns to a variable exactly once before learning not to.

Sorting one array is usually a bug

Real data comes in parallel arrays: names and scores, timestamps and readings, ids and labels. Sort the scores on their own and you've destroyed the correspondence — the values are in order and nobody knows whose they are.

np.argsort answers the better question: what order would sort this?

scores = np.array([72, 45, 90, 58])
order = np.argsort(scores)     # [1 3 0 2]

Those are positions, not values: "the smallest is at index 1, then index 3, then 0, then 2". And a list of positions is exactly what fancy indexing eats, so you can apply that one permutation to every array that lines up:

names[order]     # ['Bilal' 'Dev' 'Asha' 'Chen']
scores[order]    # [45 58 72 90]

That's "sort the table by this column" in two lines, and it generalises to any number of parallel arrays. Whenever you catch yourself wanting to sort a table, reach for argsort first.

Descending

There is no reverse= argument. Reverse the result instead:

np.sort(x)[::-1]        # values, descending
np.argsort(x)[::-1]     # the descending permutation
x[np.argsort(x)[::-1]]  # the array itself, descending

When you only need the top few

Fully sorting a million values to find the largest ten is wasteful. np.argpartition does a partial sort — it guarantees the k-th element is in its final place with everything smaller before it, and doesn't bother ordering the rest:

top3 = np.argpartition(x, -3)[-3:]   # the three largest, unordered
top3 = top3[np.argsort(x[top3])[::-1]]   # now sort just those three

Searching a sorted array

Once an array is sorted, you get binary search — logarithmic rather than linear:

a = np.array([10, 20, 30, 40])
np.searchsorted(a, 25)               # 2 — where 25 would be inserted
np.searchsorted(a, [5, 25, 45])      # [0 2 4] — several at once
np.searchsorted(a, 30, side='right') # 3 — after the equal value, not before

The classic use is bucketing without a loop: given bin edges, find which bin each value belongs to. np.digitize is a friendlier wrapper around the same idea.

Positions of extremes

np.argmax(cups)            # position of the largest, in the flattened array
np.argmax(cups, axis=0)    # per column
np.unravel_index(np.argmax(cups), cups.shape)   # as a (row, col) pair

argmax on a 2-D array with no axis flattens first, so you get a single number that indexes the flat array. np.unravel_index converts it back into coordinates, which is usually what you wanted.

And on 2-D, np.sort(m, axis=0) sorts each column independently — it scrambles rows relative to one another, which is almost always wrong for a table. Sort with argsort on the key column instead.

Practice

Write it yourself. The answer is there when you want it.

Putting the kettle on…

Starting up…

Write it yourself

not graded

Get the sort order with np.argsort(scores), then use it to print names and scores together, still matching. Print them descending as well. Then use np.searchsorted to find where 5, 25 and 45 would go in [10, 20, 30, 40]. Finish with the row and column of the best figure in cups, via np.unravel_index.

Write something and press Run — the output appears here.

Your turn

4 exercises. Write the code yourself, then press Check — a nudge and the answer are there if you want them.

Return scores sorted ascending, as a new array.

your answer

Return names ordered by ascending score.

your answer

Now names ordered by descending score — best first.

your answer

Given np.array([10, 20, 30, 40]), where would 25 be inserted to keep it sorted? Return the position.

your answer