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
- Slices are views;
a[:2].copy()if you need an independent array. &/|/~for elementwise boolean ops on arrays — never Python'sand/or/not.- Comparing floats for exact equality is fragile — use
np.allclose/np.isclose. np.reshapeis not the same as transpose — reshape just relabels the flat buffer into a new shape; it doesn't reorder rows into columns.- Integer arrays overflow silently (no error) on overflow, unlike Python ints.