NumPy Cheatsheet

Indexing and Slicing

Use this NumPy reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

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

ExpressionReturnsView?
a[i]single element or sub-arrayyes
a[i:j]sliceyes
a[i:j:k]stepped sliceyes
a[...]ellipsis sliceyes
a[[i, j]]fancy int indexno
a[bool_mask]boolean maskno
a.take(idx)like fancy but with modesno