| name | numpy |
| description | Comprehensive guide for NumPy - the fundamental package for scientific computing in Python. Use for array operations, linear algebra, random number generation, Fourier transforms, mathematical functions, and high-performance numerical computing. Foundation for SciPy, pandas, scikit-learn, and all scientific Python. |
| version | 1.26 |
| license | BSD-3-Clause |
NumPy - Numerical Python
The fundamental package for numerical computing in Python, providing multi-dimensional arrays and fast operations.
When to Use
- Working with multi-dimensional arrays and matrices
- Performing element-wise operations on arrays
- Linear algebra computations (matrix multiplication, eigenvalues, SVD)
- Random number generation and statistical distributions
- Fourier transforms and signal processing basics
- Mathematical operations (trigonometric, exponential, logarithmic)
- Broadcasting operations across different array shapes
- Vectorizing Python loops for performance
- Reading and writing numerical data to files
- Building numerical algorithms and simulations
- Serving as foundation for pandas, scikit-learn, SciPy
Reference Documentation
Official docs: https://numpy.org/doc/
Search patterns: np.array, np.zeros, np.dot, np.linalg, np.random, np.broadcast
Core Principles
Use NumPy For
| Task | Function | Example |
|---|
| Create arrays | array, zeros, ones | np.array([1, 2, 3]) |
| Mathematical ops | +, *, sin, exp | np.sin(arr) |
| Linear algebra | dot, linalg.inv | np.dot(A, B) |
| Statistics | mean, std, percentile | np.mean(arr) |
| Random numbers | random.rand, random.normal | np.random.rand(10) |
| Indexing | [], boolean, fancy | arr[arr > 0] |
| Broadcasting | Automatic | arr + scalar |
| Reshaping | reshape, flatten | arr.reshape(2, 3) |
Do NOT Use For
- String manipulation (use built-in str or pandas)
- Complex data structures (use pandas DataFrame)
- Symbolic mathematics (use SymPy)
- Deep learning (use PyTorch, TensorFlow)
- Sparse matrices (use scipy.sparse)
Quick Reference
Installation
pip install numpy
conda install numpy
pip install numpy==1.26.0
Standard Imports
import numpy as np
from numpy import linalg as la
from numpy import random as rand
from numpy import fft
Basic Pattern - Array Creation
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
zeros = np.zeros((3, 4))
ones = np.ones((2, 3))
range_arr = np.arange(0, 10, 2)
linspace_arr = np.linspace(0, 1, 5)
print(f"Array: {arr}")
print(f"Shape: {arr.shape}")
print(f"Dtype: {arr.dtype}")
Basic Pattern - Array Operations
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = a + b
d = a * b
e = a ** 2
f = np.sin(a)
g = np.exp(a)
print(f"Sum: {c}")
print(f"Product: {d}")
Basic Pattern - Linear Algebra
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
C = np.dot(A, B)
A_inv = np.linalg.inv(A)
eigenvalues, eigenvectors = np.linalg.eig(A)
print(f"Matrix product:\n{C}")
print(f"Eigenvalues: {eigenvalues}")
Critical Rules
✅ DO
- Use vectorization - Avoid Python loops, use array operations
- Specify dtype explicitly - For memory efficiency and precision control
- Use views when possible - Avoid unnecessary copies
- Broadcast properly - Understand broadcasting rules
- Check array shapes - Use
.shape frequently
- Use axis parameter - For operations along specific dimensions
- Pre-allocate arrays - Don't grow arrays in loops
- Use appropriate dtypes - int32, float64, complex128, etc.
- Copy when needed - Use
.copy() for independent arrays
- Use built-in functions - They're optimized in C
❌ DON'T
- Loop over arrays - Use vectorization instead
- Grow arrays dynamically - Pre-allocate instead
- Use Python lists for math - Convert to arrays first
- Ignore memory layout - C-contiguous vs Fortran-contiguous matters
- Mix dtypes carelessly - Know implicit type promotion rules
- Modify arrays during iteration - Can cause undefined behavior
- Use == for array comparison - Use
np.array_equal() or np.allclose()
- Assume views vs copies - Check with
.base attribute
- Ignore NaN handling - Use
np.nanmean(), np.nanstd(), etc.
- Use outdated APIs - Check for deprecated functions
Anti-Patterns (NEVER)
import numpy as np
result = []
for i in range(len(arr)):
result.append(arr[i] * 2)
result = np.array(result)
result = arr * 2
result = np.array([])
for i in range(1000):
result = np.append(result, i)
result = np.zeros(1000)
for i in range(1000):
result[i] = i
result = np.arange(1000)
if arr1 == arr2:
print("Equal")
if np.array_equal(arr1, arr2):
print("Equal")
if np.allclose(arr1, arr2, rtol=1e-5):
print("Close enough")
arr = np.array([1, 2, 3])
arr[0] = 1.5
arr = np.array([1, 2, 3], dtype=)
arr[] =
a = np.array([, , ])
b = a
b[] =
a = np.array([, , ])
b = a.copy()
b[] =
Array Creation
Basic Array Creation
import numpy as np
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
arr3 = np.array([1, 2, 3], dtype=np.float64)
arr4 = np.array([1, 2, 3], dtype=np.int32)
arr5 = np.array((1, 2, 3))
arr6 = np.array([1+2j, 3+4j])
print(f"1D array: {arr1}")
print(f"2D array:\n{arr2}")
print(f"Float array: {arr3}")
Special Array Creation
import numpy as np
zeros = np.zeros((3, 4))
ones = np.ones((2, 3, 4))
empty = np.empty((2, 2))
full = np.full((3, 3), 7)
identity = np.eye(4)
diag = np.diag([1, 2, 3, 4])
print(f"Zeros shape: {zeros.shape}")
print(f"Identity:\n{identity}")
Range-Based Creation
import numpy as np
a = np.arange(10)
b = np.arange(2, 10)
c = np.arange(0, 10, 2)
d = np.arange(0, 1, 0.1)
e = np.linspace(0, 1, 5)
f = np.linspace(0, 10, 100)
g = np.logspace(0, 2, 5)
h = np.geomspace(1, 1000, 4)
print(f"Arange: {a}")
print(f"Linspace: {e}")
Array Copies and Views
import numpy as np
original = np.array([1, 2, 3, 4, 5])
view = original[:]
view[0] = 999
copy = original.copy()
copy[0] = 777
print(f"Is view? {view.base is original}")
print(f"Is copy? {copy.base is None}")
slice_view = original[1:3]
boolean_copy = original[original > 2]
Array Indexing and Slicing
Basic Indexing
import numpy as np
arr = np.array([10, 20, 30, 40, 50])
print(arr[0])
print(arr[-1])
print(arr[1:4])
print(arr[:3])
print(arr[2:])
print(arr[::2])
print(arr[-3:-1])
print(arr[::-1])
Multi-Dimensional Indexing
import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(arr[0, 0])
print(arr[1, 2])
print(arr[-1, -1])
print(arr[0])
print(arr[1, :])
print(arr[:, 0])
print(arr[:, 1])
print(arr[0:2, 1:3])
print(arr[::2, ::2])
Boolean Indexing
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
mask = arr > 5
print(mask)
filtered = arr[arr > 5]
print(filtered)
result = arr[(arr > 3) & (arr < 8)]
print(result)
result = arr[(arr < 3) | (arr > 8)]
print(result)
result = arr[~(arr > 5)]
print(result)
Fancy Indexing
import numpy as np
arr = np.array([10, 20, 30, 40, 50])
indices = np.array([0, 2, 4])
result = arr[indices]
print(result)
arr2d = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
rows = np.array([0, 2])
cols = np.array([1, 2])
result = arr2d[rows, cols]
print(result)
mask = arr > 25
indices_of_large = np.where(mask)[0]
print(indices_of_large)
Array Operations
Element-wise Operations
import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a ** 2)
print(a // b)
print(a % b)
print(a + 10)
print(a * 2)
Mathematical Functions
import numpy as np
x = np.array([0, np.pi/6, np.pi/4, np.pi/3, np.pi/2])
sin_x = np.sin(x)
cos_x = np.cos(x)
tan_x = np.tan(x)
arcsin_x = np.arcsin([0, 0.5, 1])
arr = np.array([1, 2, 3, 4])
exp_arr = np.exp(arr)
log_arr = np.log(arr)
log10_arr = np.log10(arr)
floats = np.array([1.2, 2.7, 3.5, 4.9])
print(np.round(floats))
print(np.floor(floats))
print(np.ceil(floats))
print(np.abs([-1, -2, 3, -4]))
Aggregation Functions
import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(np.sum(arr))
print(np.sum(arr, axis=0))
print(np.sum(arr, axis=1))
print(np.mean(arr))
print(np.std(arr))
print(np.min(arr))
print(np.max(arr))
print(np.argmin(arr))
print(np.argmax(arr))
print(np.median(arr))
print(np.percentile(arr, 25))
Broadcasting
Broadcasting Rules
import numpy as np
arr = np.array([1, 2, 3, 4])
result = arr + 10
print(result)
arr1d = np.array([1, 2, 3])
arr2d = np.array([[10], [20], [30]])
result = arr1d + arr2d
print(result)
data = np.random.randn(100, 3)
mean = np.mean(data, axis=0)
std = np.std(data, axis=0)
standardized = (data - mean) / std
Explicit Broadcasting
import numpy as np
arr = np.array([1, 2, 3])
broadcasted = np.broadcast_to(arr, (4, 3))
print(broadcasted)
arr1d = np.array([1, 2, 3])
col_vector = arr1d[:, np.newaxis]
row_vector = arr1d[np.newaxis, :]
outer = col_vector * row_vector
print(outer)
Linear Algebra
Matrix Operations
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
C = np.dot(A, B)
C = A @ B
D = A * B
A_T = A.T
trace = np.trace(A)
A_squared = np.linalg.matrix_power(A, 2)
print(f"Matrix product:\n{C}")
print(f"Transpose:\n{A_T}")
print(f"Trace: {trace}")
Solving Linear Systems
import numpy as np
A = np.array([[3, 1], [1, 2]])
b = np.array([9, 8])
x = np.linalg.solve(A, b)
print(f"Solution: {x}")
print(f"Verification: {np.allclose(A @ x, b)}")
A_inv = np.linalg.inv(A)
print(f"Inverse:\n{A_inv}")
det = np.linalg.det(A)
print(f"Determinant: {det}")
Eigenvalues and Eigenvectors
import numpy as np
A = np.array([[1, 2], [2, 1]])
eigenvalues, eigenvectors = np.linalg.eig(A)
print(f"Eigenvalues: {eigenvalues}")
print(f"Eigenvectors:\n{eigenvectors}")
for i in range(len(eigenvalues)):
lam = eigenvalues[i]
v = eigenvectors[:, i]
left = A @ v
right = lam * v
print(f"Eigenvalue {i}: {np.allclose(left, right)}")
Singular Value Decomposition (SVD)
import numpy as np
A = np.array([[1, 2, 3],
[4, 5, 6]])
U, s, Vt = np.linalg.svd(A)
S = np.zeros((2, 3))
S[:2, :2] = np.diag(s)
A_reconstructed = U @ S @ Vt
print(f"Original:\n{A}")
print(f"Reconstructed:\n{A_reconstructed}")
print(f"Close? {np.allclose(A, A_reconstructed)}")
print(f"Singular values: {s}")
Matrix Norms
import numpy as np
A = np.array([[1, 2], [3, 4]])
norm_fro = np.linalg.norm(A)
norm_1 = np.linalg.norm(A, ord=1)
norm_inf = np.linalg.norm(A, ord=np.inf)
norm_2 = np.linalg.norm(A, ord=2)
print(f"Frobenius: {norm_fro:.4f}")
print(f"1-norm: {norm_1:.4f}")
print(f"2-norm: {norm_2:.4f}")
print(f"inf-norm: {norm_inf:.4f}")
Random Number Generation
Basic Random Generation
import numpy as np
np.random.seed(42)
rand_uniform = np.random.rand(5)
rand_2d = np.random.rand(3, 4)
rand_int = np.random.randint(0, 10, size=5)
rand_int_2d = np.random.randint(0, 100, size=(3, 3))
rand_normal = np.random.randn(1000)
rand_normal_custom = np.random.normal(loc=5, scale=2, size=1000)
choices = np.random.choice(['a', 'b', 'c'], size=10)
weighted_choices = np.random.choice([1, 2, 3], size=100, p=[0.1, 0.3, 0.6])
Statistical Distributions
import numpy as np
uniform = np.random.uniform(low=0, high=10, size=1000)
normal = np.random.normal(loc=0, scale=1, size=1000)
exponential = np.random.exponential(scale=2, size=1000)
binomial = np.random.binomial(n=10, p=0.5, size=1000)
poisson = np.random.poisson(lam=3, size=1000)
beta = np.random.beta(a=2, b=5, size=1000)
chisq = np.random.chisquare(df=2, size=1000)
Modern Random Generator (numpy.random.Generator)
import numpy as np
rng = np.random.default_rng(seed=42)
rand = rng.random(size=10)
ints = rng.integers(low=0, high=100, size=10)
normal = rng.normal(loc=0, scale=1, size=10)
arr = np.arange(10)
rng.shuffle(arr)
sample = rng.choice(100, size=10, replace=False)
print(f"Random: {rand}")
print(f"Shuffled: {arr}")
Reshaping and Manipulation
Reshaping Arrays
import numpy as np
arr = np.arange(12)
arr_2d = arr.reshape(3, 4)
arr_3d = arr.reshape(2, 2, 3)
arr_auto = arr.reshape(3, -1)
flat = arr_2d.flatten()
flat = arr_2d.ravel()
arr_t = arr_2d.T
print(f"Original shape: {arr.shape}")
print(f"2D shape: {arr_2d.shape}")
print(f"3D shape: {arr_3d.shape}")
Stacking and Splitting
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.array([7, 8, 9])
vstacked = np.vstack([a, b, c])
print(vstacked)
hstacked = np.hstack([a, b, c])
print(hstacked)
col_stacked = np.column_stack([a, b, c])
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
concat_axis0 = np.concatenate([arr1, arr2], axis=0)
concat_axis1 = np.concatenate([arr1, arr2], axis=1)
arr = np.arange(12)
split = np.split(arr, 3)
print(split)
File I/O
Text Files
import numpy as np
data = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
np.savetxt('data.txt', data)
np.savetxt('data.csv', data, delimiter=',')
np.savetxt('data_formatted.txt', data, fmt='%.2f')
loaded = np.loadtxt('data.txt')
loaded_csv = np.loadtxt('data.csv', delimiter=',')
loaded_skip = np.loadtxt('data.txt', skiprows=1)
loaded_cols = np.loadtxt('data.csv', delimiter=',', usecols=(0, 2))
Binary Files (.npy, .npz)
import numpy as np
arr = np.random.rand(100, 100)
np.save('array.npy', arr)
loaded = np.load('array.npy')
arr1 = np.random.rand(10, 10)
arr2 = np.random.rand(20, 20)
np.savez('arrays.npz', first=arr1, second=arr2)
loaded = np.load('arrays.npz')
loaded_arr1 = loaded['first']
loaded_arr2 = loaded['second']
np.savez_compressed('arrays_compressed.npz', arr1=arr1, arr2=arr2)
Advanced Techniques
Universal Functions (ufuncs)
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
result = np.sqrt(arr)
result = np.exp(arr)
result = np.log(arr)
def my_func(x):
return x**2 + 2*x + 1
vectorized = np.vectorize(my_func)
result = vectorized(arr)
@np.vectorize
def better_func(x):
return x**2 + 2*x + 1
Structured Arrays
import numpy as np
dt = np.dtype([('name', 'U20'), ('age', 'i4'), ('weight', 'f8')])
data = np.array([
('Alice', 25, 55.5),
('Bob', 30, 70.2),
('Charlie', 35, 82.1)
], dtype=dt)
names = data['name']
ages = data['age']
sorted_data = np.sort(data, order='age')
print(f"Names: {names}")
print(f"Sorted by age:\n{sorted_data}")
Memory Layout and Performance
import numpy as np
arr_c = np.array([[1, 2, 3], [4, 5, 6]], order='C')
arr_f = np.array([[1, 2, 3], [4, 5, 6]], order='F')
print(f"C-contiguous? {arr_c.flags['C_CONTIGUOUS']}")
print(f"F-contiguous? {arr_c.flags['F_CONTIGUOUS']}")
arr_made_c = np.ascontiguousarray(arr_f)
arr_made_f = np.asfortranarray(arr_c)
print(f"Memory (bytes): {arr_c.nbytes}")
print(f"Item size: {arr_c.itemsize}")
Advanced Indexing with ix_
import numpy as np
arr = np.arange(20).reshape(4, 5)
rows = np.array([0, 2])
cols = np.array([1, 3, 4])
result = arr[np.ix_(rows, cols)]
print(result)
Practical Workflows
Statistical Analysis
import numpy as np
np.random.seed(42)
data = np.random.normal(loc=100, scale=15, size=1000)
mean = np.mean(data)
median = np.median(data)
std = np.std(data)
var = np.var(data)
q25, q50, q75 = np.percentile(data, [25, 50, 75])
counts, bins = np.histogram(data, bins=20)
data2 = data + np.random.normal(0, 5, size=1000)
corr = np.corrcoef(data, data2)[0, 1]
print(f"Mean: {mean:.2f}")
print(f"Median: {median:.2f}")
print(f"Std: {std:.2f}")
print(f"IQR: [{q25:.2f}, {q75:.2f}]")
print(f"Correlation: {corr:.3f}")
Monte Carlo Simulation
import numpy as np
def estimate_pi(n_samples=1000000):
"""Estimate π using Monte Carlo method."""
x = np.random.rand(n_samples)
y = np.random.rand(n_samples)
inside = (x**2 + y**2) <= 1
pi_estimate = 4 * np.sum(inside) / n_samples
return pi_estimate
pi_est = estimate_pi(10000000)
print(f"π estimate: {pi_est:.6f}")
print(f"Error: {abs(pi_est - np.pi):.6f}")
Polynomial Fitting
import numpy as np
x = np.linspace(0, 10, 50)
y_true = 2*x**2 + 3*x + 1
y_noisy = y_true + np.random.normal(0, 10, size=50)
coeffs = np.polyfit(x, y_noisy, deg=2)
print(f"Coefficients: {coeffs}")
y_pred = np.polyval(coeffs, x)
residuals = y_noisy - y_pred
rmse = np.sqrt(np.mean(residuals**2))
print(f"RMSE: {rmse:.2f}")
poly = np.poly1d(coeffs)
print(f"Polynomial: {poly}")
Image Processing Basics
import numpy as np
image = np.random.rand(100, 100)
rotated = np.rot90(image)
flipped_v = np.flipud(image)
flipped_h = np.fliplr(image)
transposed = image.T
normalized = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
print(f"Original shape: {image.shape}")
print(f"Value range: [{image.min():.2f}, {image.max():.2f}]")
Distance Matrices
import numpy as np
points = np.random.rand(100, 2)
diff = points[:, np.newaxis, :] - points[np.newaxis, :, :]
distances = np.sqrt(np.sum(diff**2, axis=2))
print(f"Distance matrix shape: {distances.shape}")
print(f"Max distance: {distances.max():.4f}")
for i in range(5):
dists = distances[i].copy()
dists[i] = np.inf
nearest = np.argmin(dists)
print(f"Point {i} nearest to point {nearest}, distance: {distances[i, nearest]:.4f}")
Sliding Window Operations
import numpy as np
def sliding_window_view(arr, window_size):
"""Create sliding window views of array."""
shape = (arr.shape[0] - window_size + 1, window_size)
strides = (arr.strides[0], arr.strides[0])
return np.lib.stride_tricks.as_strided(arr, shape=shape, strides=strides)
data = np.random.rand(100)
windows = sliding_window_view(data, window_size=10)
window_means = np.mean(windows, axis=1)
window_stds = np.std(windows, axis=1)
print(f"Number of windows: {len(windows)}")
print(f"First window mean: {window_means[0]:.4f}")
Performance Optimization
Vectorization Examples
import numpy as np
import time
def sum_python_loop(arr):
total = 0
for x in arr:
total += x**2
return total
def sum_vectorized(arr):
return np.sum(arr**2)
arr = np.random.rand(1000000)
start = time.time()
result1 = sum_python_loop(arr)
time_loop = time.time() - start
start = time.time()
result2 = sum_vectorized(arr)
time_vec = time.time() - start
print(f"Loop time: {time_loop:.4f}s")
print(f"Vectorized time: {time_vec:.4f}s")
print(f"Speedup: {time_loop/time_vec:.1f}x")
Memory-Efficient Operations
import numpy as np
def inefficient(arr):
temp1 = arr * 2
temp2 = temp1 + 5
temp3 = temp2 ** 2
return temp3
def efficient(arr):
result = arr.copy()
result *= 2
result += 5
result **= 2
return result
def most_efficient(arr):
return (arr * 2 + 5) ** 2
Using numexpr for Complex Expressions
import numpy as np
a = np.random.rand(10000000)
b = np.random.rand(10000000)
result = 2*a + 3*b**2 - np.sqrt(a)
Common Pitfalls and Solutions
NaN Handling
import numpy as np
arr = np.array([1, 2, np.nan, 4, 5, np.nan])
mean = np.mean(arr)
mean = np.nanmean(arr)
std = np.nanstd(arr)
sum_val = np.nansum(arr)
has_nan = np.isnan(arr).any()
where_nan = np.where(np.isnan(arr))[0]
arr_clean = arr[~np.isnan(arr)]
print(f"Mean (nan-safe): {mean}")
print(f"NaN positions: {where_nan}")
Integer Division Pitfall
import numpy as np
a = np.array([1, 2, 3])
b = np.array([2, 2, 2])
result = a / b
a_int = np.array([1, 2, 3], dtype=np.int32)
b_int = np.array([2, 2, 2], dtype=np.int32)
result_float = a_int / b_int
result_int = a_int // b_int
print(f"Float division: {result_float}")
print(f"Integer division: {result_int}")
Array Equality
import numpy as np
a = np.array([1.0, 2.0, 3.0])
b = np.array([1.0, 2.0, 3.0])
equal_elements = a == b
all_equal = np.all(a == b)
array_equal = np.array_equal(a, b)
c = a + 1e-10
close_enough = np.allclose(a, c, rtol=1e-5, atol=1e-8)
print(f"All equal: {all_equal}")
print(f"Arrays equal: {array_equal}")
print(f"Close enough: {close_enough}")
Memory Leaks with Views
import numpy as np
large_array = np.random.rand(1000000, 100)
small_view = large_array[0:10]
del large_array
large_array = np.random.rand(1000000, 100)
small_copy = large_array[0:10].copy()
del large_array
print(f"Is view? {small_view.base is not None}")
print(f"Is copy? {small_copy.base is None}")
This comprehensive NumPy guide covers 50+ examples across all major array operations and numerical computing workflows!