runtime
202 / 250
lesson 202 NumPy Foundations · advanced

Indexing, slicing and masks

A 2-D array is a table of numbers. One index pair picks a cell, a slice picks a row or a column, and a True/False mask picks every value that passes a test.

You'll be able to
  • Read a cell, a row and a column of a 2-D array with [row, column] and :
  • Use a boolean mask from a comparison to keep matching values, also from a second array of the same length
  • Explain why a slice is a view of the original and when to call copy()
The idea

Readings from several stations over several days form a table: one row per station, one column per day. NumPy stores that as a 2-D array, and its shape is (rows, columns). Inside the brackets, a comma separates the position along each dimension: tmax[1, 0] is row 1, column 0. A colon on its own means *all of them*, so tmax[:, 4] is column 4 from every row, and tmax[0, 1:4] is part of row 0.

Run each example to see what it prints. Running examples doesn't count toward progress.

example-1.py · Three stations, five days
import numpy as np

stations = ["Wichita", "Orlando", "Sioux Falls"]
# Daily highs (C), 1 to 5 January 2024: one row per station, one column per day
tmax = np.array([
    [-0.5, 6.7, 9.4, 7.2, 1.7],
    [22.2, 17.8, 21.7, 18.3, 23.3],
    [1.1, 2.8, -1.0, -1.0, 1.1],
])
print(tmax.shape)
print(stations[1], tmax[1, 0])
print(tmax[2])
print(tmax[:, 4])
print(tmax[0, 1:4])
example-2.py · A row that isn't there
import numpy as np

tmax = np.array([[-0.5, 6.7], [22.2, 17.8], [1.1, 2.8]])
print(tmax[3, 0])

A comparison on an array compares every value and gives back an array of True/False, the same length. That mask goes inside the brackets: values[mask] keeps the values where the mask is True, in order. The mask can come from a different array of the same length, which is how you ask *on which dates was it below freezing?* Because True counts as 1, mask.sum() counts the matches.

example-3.py · Days that stayed below freezing
import numpy as np

dates = np.array(["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04",
                  "2024-01-05", "2024-01-06", "2024-01-07"])
tmax = np.array([1.1, 2.8, -1.0, -1.0, 1.1, -0.5, -4.9])  # Sioux Falls
freezing = tmax < 0
print(freezing)
print(dates[freezing])
print(freezing.sum(), "of", tmax.size, "days stayed below 0 C")

Views and copies. A slice such as tmax[:3] does not copy anything: it is a view, a window onto the same memory. Changing a value through the view changes the original, which is fast but surprising. A mask always builds a new array. When you want to change values without touching the original, call copy() first.

When to use it: a position when you know where the value is, a slice for a run of rows or columns, a mask when you know the rule but not the positions. Mistakes to avoid: forgetting the comma (tmax[1][0] works but tmax[1, 0] is the array way), editing a slice you meant to copy, and masking with an array of a different length.

Review
  • a[row, col] picks a cell; : means every row or column; slices stop before their end.
  • A comparison makes a True/False mask; values[mask] keeps the matches and mask.sum() counts them.
  • Slices are views of the original; masks build new arrays; copy() makes a separate array to change.
  • Next: arithmetic between arrays of different shapes, and the rule that decides when it works.
Practise this

Loading your progress…

To master this lesson, solve both challenges without hints or the answer, and pass the concept check.

Indexing, slicing and masks — NumPy Foundations · Runtime