NumPy Cheatsheet
Indexing and Slicing
Use this NumPy reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Basic Indexing (single elements)
import numpy as np a = np.array([10, 20, 30, 40, 50]) a[0] # 10 a[-1] # 50 a[-2] # 40 b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) b[0, 0] # 1 — preferred multi-axis syntax b[0][0] # 1 — equivalent but slower (creates intermediate view) b[-1, -1] # 9 b[1, 2] # 6
Basic Slicing
Syntax: start:stop:step along each axis. All parts optional. Returns a view.
a = np.arange(10) # [0, 1, 2, ..., 9] a[2:5] # [2, 3, 4] stop is exclusive a[:3] # [0, 1, 2] a[7:] # [7, 8, 9] a[::2] # [0, 2, 4, 6, 8] a[::-1] # [9, 8, ..., 0] reversed a[1:8:2] # [1, 3, 5, 7] b = np.arange(12).reshape(3, 4) b[0, :] # first row → [0, 1, 2, 3] b[:, 1] # second col → [1, 5, 9] b[1:, ::2] # rows 1+, every other col b[:2, 1:3] # top-left 2×2 sub-matrix
Ellipsis and newaxis
c = np.ones((2, 3, 4, 5)) c[0, ..., 2] # ... expands to all middle axes → shape (3, 4) c[np.newaxis, ...] # add axis at front → shape (1, 2, 3, 4, 5) c[:, np.newaxis] # add axis at position 1 # np.newaxis is just None a[:, None] # equivalent to a[:, np.newaxis]
Fancy Indexing (always returns a copy)
Integer array indexing
a = np.array([10, 20, 30, 40, 50]) idx = np.array([0, 2, 4]) a[idx] # [10, 30, 50] a[[0, 2, 4]] # same, inline b = np.array([[1, 2], [3, 4], [5, 6]]) b[[0, 2], :] # rows 0 and 2 → [[1,2],[5,6]] b[[0, 1], [1, 0]] # elements (0,1) and (1,0) → [2, 3] — paired indexing
Selecting rows/cols independently
rows = np.array([0, 2]) cols = np.array([1]) b[np.ix_(rows, cols)] # outer product of indices → shape (2, 1)
Nested fancy indexing
a = np.arange(27).reshape(3, 3, 3) a[[0, 1], :, [2, 1]] # shape (2, 3) — axes 0 and 2 zipped
Boolean / Mask Indexing
a = np.array([1, -2, 3, -4, 5]) mask = a > 0 a[mask] # [1, 3, 5] a[a > 0] # same inline a[a < 0] = 0 # in-place assignment through mask b = np.arange(12).reshape(3, 4) b[b % 2 == 0] # all even values, 1-D result (flattens)
Gotcha: boolean indexing always returns a copy, not a view.
Assignment via Indexing
a = np.zeros(5) a[2] = 9 # scalar assigned to one element a[1:4] = [7, 8, 9] # slice assignment (broadcasts if right side is scalar) a[[0, 4]] = 99 # fancy-index assignment a[a < 5] = -1 # mask assignment # Repeated fancy-index writes: last write wins (no accumulation) a = np.zeros(5) a[[1, 1]] = [10, 20] # a[1] == 20, not 30 # Use np.add.at for accumulation np.add.at(a, [1, 1], [10, 20]) # a[1] == 30
np.take and np.choose
a = np.array([10, 20, 30, 40]) np.take(a, [0, 3, 1]) # [10, 40, 20] np.take(b, [0, 2], axis=0) # rows 0 and 2 of 2-D array choices = np.array([[0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23]]) np.choose([0, 1, 2, 0], choices) # [0, 11, 22, 3] — pick from each row
Searching for Indices
a = np.array([10, 20, 30, 20, 10]) np.where(a == 20) # (array([1, 3]),) np.where(a == 20)[0] # [1, 3] np.nonzero(a) # same as np.where — indices of nonzero elements np.flatnonzero(a > 15) # flat indices np.argmax(a) # index of max → 2 np.argmin(a) # index of min → 0 np.argmax(b, axis=0) # per-column max index np.argsort(a) # indices that would sort a np.argpartition(a, 2) # partial-sort indices (nth smallest at index 2) np.searchsorted([1, 3, 5], 4) # insertion index → 2 np.searchsorted([1, 3, 5], [2, 4]) # [1, 2] np.searchsorted([1, 3, 5], 3, side="right") # → 2
Advanced: np.unravel_index / np.ravel_multi_index
a = np.arange(24).reshape(4, 6) flat_idx = np.argmax(a) # 23 (flat index) np.unravel_index(flat_idx, a.shape) # (3, 5) — row, col np.ravel_multi_index((3, 5), (4, 6)) # 23 — reverse: multi → flat np.ravel_multi_index(([1, 2], [3, 4]), (4, 6)) # [9, 16]
Slicing Summary Table
| Expression | Returns | View? |
|---|---|---|
a[i] | single element or sub-array | yes |
a[i:j] | slice | yes |
a[i:j:k] | stepped slice | yes |
a[...] | ellipsis slice | yes |
a[[i, j]] | fancy int index | no |
a[bool_mask] | boolean mask | no |
a.take(idx) | like fancy but with modes | no |