← All cheatsheets

NumPy Cheatsheet

Array creation, indexing, broadcasting, statistics, random generation, and file I/O.

Import & Array Creation

import numpy as np

np.array([1, 2, 3])                 # from a list -> 1-D array
np.array([[1, 2], [3, 4]])          # from nested lists -> 2-D array
np.zeros((2, 3))                    # all zeros, shape (2,3)
np.ones((2, 3))
np.full((2, 3), 7)                  # filled with a scalar
np.empty((2, 3))                    # uninitialized (garbage values, fastest)
np.zeros_like(a); np.ones_like(a); np.full_like(a, 7); np.empty_like(a)
np.arange(0, 10, 2)                 # like range(): start, stop, step
np.linspace(0, 1, 5)                # 5 evenly spaced points from 0 to 1 (inclusive)
np.eye(3)                           # 3x3 identity matrix
np.diag([1, 2, 3])                  # diagonal matrix from a vector

Array Attributes

a.shape      # tuple of dimensions, e.g. (3, 4)
a.ndim       # number of dimensions
a.size       # total number of elements
a.dtype      # element type, e.g. int64, float32
a.itemsize   # bytes per element
a.nbytes     # total bytes (== size * itemsize)

Indexing & Slicing

a[0]; a[-1]                 # first / last (negative indices count from the end)
a[row, col]                 # 2-D element access, e.g. a[0, 1]
a[:, 0]                     # all rows, column 0
a[1:, 1:]                   # sub-matrix, dropping the first row & column
a[::2]                      # every other element
a[::-1]                     # reversed
a[a > 5]                    # boolean mask -> only matching elements
a[(a > 5) & (a < 10)]       # combine masks with & / | (NOT `and`/`or`)
np.where(cond, x, y)        # elementwise "x if cond else y"
a[[0, 2, 4]]                # fancy indexing: pick specific rows/indices

Slicing returns a view (shares memory with the original); fancy/boolean indexing returns a copy. Assigning through a slice mutates the original array.

Shape Manipulation

a.reshape(rows, cols)        # same data, new shape (must match total size)
a.reshape(-1)                # flatten to 1-D (also: a.flatten(), a.ravel())
a.T; a.transpose()           # transpose (swap axes)
a.squeeze()                  # remove all size-1 dimensions
np.expand_dims(a, axis=0)    # insert a new size-1 dimension
np.concatenate([a, b], axis=0)
np.vstack([a, b])            # stack as rows (like concatenate axis=0)
np.hstack([a, b])            # stack as columns / end-to-end for 1-D
np.dstack([a, b])            # stack along a new third axis
np.stack([a, b], axis=0)     # stack along a brand-new axis
np.split(a, 3)               # split into 3 equal parts along axis 0
np.delete(a, [0, 2], axis=0) # delete rows/columns by index

Math & Broadcasting

a + b; a - b; a * b; a / b   # elementwise (NOT matrix multiply)
a @ b; np.matmul(a, b)       # matrix multiplication
np.dot(a, b)                 # dot product / matmul depending on shapes
a ** 2; np.sqrt(a); np.exp(a); np.log(a)
np.add(a, b, dtype=np.float64)  # ufuncs accept a dtype override

Broadcasting rule: compare shapes from the right; dimensions are compatible if they're equal or one of them is 1. A shape-(3,) array broadcasts against a shape-(2,3) array (repeated across rows); a shape-(2,1) array broadcasts against (2,3) (repeated across columns).

Aggregations & Statistics

a.sum(); a.mean(); a.std(); a.var()
a.min(); a.max(); a.argmin(); a.argmax()   # argmin/argmax return *positions*
np.median(a); np.percentile(a, 75); np.quantile(a, 0.75)
np.ptp(a)                     # max - min ("peak to peak")
a.sum(axis=0)                 # axis=0 -> collapse rows (per-column result)
a.sum(axis=1)                 # axis=1 -> collapse columns (per-row result)
np.cumsum(a); np.cumprod(a)
np.average(a, weights=w)      # weighted average
np.cov(a); np.corrcoef(a)     # covariance / correlation matrix (rows = variables)
np.histogram(a, bins=10, range=(lo, hi))   # -> (counts, bin_edges)

NaN-safe variants ignore missing values: np.nanmean, np.nansum, np.nanstd, np.nanmax, np.nanmin, np.nanmedian, np.nanquantile, np.nanvar.

Sorting & Searching

np.sort(a)                    # sorted copy (per-row by default for 2-D)
np.sort(a, axis=None)         # sort the fully flattened array
a.argsort()                   # indices that WOULD sort the array
a[np.argsort(a[:, 0])]        # sort rows by column 0
np.unique(a)                  # sorted unique values
np.unique(a, return_counts=True)   # + how many times each value appears
np.unique(a, return_index=True)    # + index of first occurrence
np.where(cond)                # indices where cond is True (tuple of arrays)
np.argwhere(cond)             # same info, shaped (n_matches, n_dims)
np.nonzero(a)

Dtypes & Casting

a.astype(np.float32)          # convert element type (returns a new array)
a.view(np.int32)              # reinterpret the same bytes as a different dtype
np.isnan(a)                   # elementwise NaN check
common dtypes: int8/16/32/64, uint8, float16/32/64, complex64/128, bool_, str_

Random Numbers

Prefer the modern Generator API over the legacy np.random.seed/np.random.rand:

rng = np.random.default_rng(seed=365)     # or: Generator(PCG64(seed=365))
rng.random((3, 3))            # uniform floats in [0, 1)
rng.integers(low, high, size=(3, 3))
rng.normal(loc=0, scale=1, size=(3, 3))
rng.binomial(n=100, p=0.4, size=(5, 5))
rng.poisson(lam=10, size=(5, 5))
rng.choice([1, 2, 3], size=5, p=[0.2, 0.3, 0.5])
rng.shuffle(a)                 # in-place shuffle

The legacy np.random.seed(0) + np.random.rand(...) style still works and is common in older code/tests, but isn't thread-safe and is being phased out.

File I/O (works with real files OR in-memory io.BytesIO/io.StringIO)

np.savetxt("f.csv", a, delimiter=",")          # human-readable text
np.loadtxt("f.csv", delimiter=",")             # fast, but fails on missing values
np.genfromtxt("f.csv", delimiter=",",          # tolerant of missing/malformed data
              filling_values=0, skip_header=1, skip_footer=1, usecols=(0, 2))
np.save("f.npy", a); np.load("f.npy")          # binary, single array, exact round-trip
np.savez("f.npz", first=a, second=b)           # multiple named arrays in one archive
np.load("f.npz")["first"]                      # access by name

Linear Algebra (np.linalg)

np.linalg.inv(A)          # matrix inverse
np.linalg.det(A)          # determinant
np.linalg.solve(A, b)     # solve Ax = b
np.linalg.eig(A)          # eigenvalues & eigenvectors
np.linalg.norm(a)         # vector/matrix norm

Gotchas

Also see: Pandas, PyTorch