Python for Data course menu
NumPy Indexing, Slicing and Boolean Masks
Select data from NumPy arrays: indexing and slicing 1D and 2D arrays, rows and columns, boolean masks for filtering, fancy indexing with lists of positions, and the difference between views and copies.
On this page
Selecting the right part of an array is something you will do constantly. NumPy supports Python-style indexing and slicing, plus two powerful extras: boolean masks and fancy indexing.
1D indexing and slicing#
Works like a Python list: indexes start at 0, negative indexes count from the end, and slices exclude the stop position.
import numpy as np
a = np.array([10, 20, 30, 40, 50, 60])
print(a[0], a[-1])
print(a[1:4])
print(a[::2])
print(a[::-1])10 60
[20 30 40]
[10 30 50]
[60 50 40 30 20 10]2D: rows and columns#
Use one pair of brackets with a comma: arr[rows, cols]. A colon on its own means "everything along this dimension".
import numpy as np
m = np.array([
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
])
print(m[1, 2]) # one element
print(m[0]) # first row
print(m[:, 1]) # second column
print(m[:2, 2:]) # top-right 2 x 2 block
print(m[-1, ::-1]) # last row reversed7
[1 2 3 4]
[ 2 6 10]
[[3 4]
[7 8]]
[12 11 10 9]Boolean masks#
Comparing an array gives a boolean array of the same shape. Using it as an index keeps only the elements where it is True. This is how you filter data in NumPy (and, as you will see, in pandas):
import numpy as np
temps = np.array([18, 25, 31, 22, 35, 29, 16])
hot = temps > 28
print(hot)
print(temps[hot])
print(temps[(temps >= 20) & (temps <= 30)])
print(temps[~hot]) # ~ means "not"[False False True False True True False]
[31 35 29]
[25 22 29]
[18 25 22 16]You can also assign through a mask, for example to cap extreme values:
import numpy as np
readings = np.array([12, 250, 18, -5, 30])
readings[readings > 100] = 100
readings[readings < 0] = 0
print(readings)
print(np.clip(np.array([12, 250, 18, -5, 30]), 0, 100)) # the same in one call[ 12 100 18 0 30]
[ 12 100 18 0 30]Fancy indexing#
Pass a list (or array) of positions to pick several elements in any order:
import numpy as np
names = np.array(["Asha", "Ravi", "Meera", "John", "Priya"])
scores = np.array([88, 72, 95, 64, 81])
order = np.argsort(scores)[::-1] # positions from highest score to lowest
print(order)
print(names[order])
print(scores[[0, 2, 4]])[2 0 4 1 3]
['Meera' 'Asha' 'Priya' 'Ravi' 'John']
[88 95 81]np.argsort returns the positions that would sort the array; indexing another array with them sorts both together.
Views and copies#
A slice of a NumPy array is a view: it shares memory with the original, so changing it changes the original. Boolean and fancy indexing return copies.
import numpy as np
a = np.array([1, 2, 3, 4, 5])
part = a[1:4]
part[0] = 99
print(a) # changed through the view
b = np.array([1, 2, 3, 4, 5])
safe = b[1:4].copy()
safe[0] = 99
print(b) # unchanged[ 1 99 3 4 5]
[1 2 3 4 5]Python list slices are copies, so this behaviour surprises many people. Call .copy() when you want an independent array.
Common mistakes#
Practice#
Practice exercise
Daily step counts for two weeks are in a 2 × 7 array: [[4200, 8100, 10500, 3900, 12000, 9800, 6100], [7300, 11000, 5600, 9900, 13400, 2800, 8800]]. Print: (1) the second week, (2) every Wednesday (third column), (3) all days with at least 10,000 steps, and (4) how many such days there were.
Show hint
arr[1], arr[:, 2], a boolean mask arr >= 10000 used as an index (it flattens the result), and .sum() on the mask.
Show solution
import numpy as np
steps = np.array([
[4200, 8100, 10500, 3900, 12000, 9800, 6100],
[7300, 11000, 5600, 9900, 13400, 2800, 8800],
])
print(steps[1])
print(steps[:, 2])
print(steps[steps >= 10000])
print((steps >= 10000).sum())[ 7300 11000 5600 9900 13400 2800 8800]
[10500 5600]
[10500 12000 11000 13400]
4Key takeaway#
Finished this lesson?