Master array operations and numerical computing with NumPy
NumPy (Numerical Python) is the fundamental package for scientific computing in Python. It provides support for large, multi-dimensional arrays and matrices, along with a collection of mathematical functions to operate on these arrays efficiently.
- **Fast**: Written in C, NumPy operations are much faster than Python lists - **Memory Efficient**: Uses contiguous memory blocks - **Convenient**: Rich set of mathematical functions - **Foundation**: Base for pandas, scikit-learn, TensorFlow, and PyTorch
Let's start by creating arrays in different ways:
import numpy as np
# From Python list
arr1 = np.array([1, 2, 3, 4, 5])
print(f"1D Array: {arr1}")
print(f"Shape: {arr1.shape}, Dtype: {arr1.dtype}")
# 2D Array (Matrix)
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(f"\n2D Array:\n{arr2}")
print(f"Shape: {arr2.shape}")
# Zeros and Ones
zeros = np.zeros((3, 4))
ones = np.ones((2, 3))
print(f"\nZeros:\n{zeros}")
# Range of values
range_arr = np.arange(0, 10, 2) # Start, stop, step
print(f"\nRange: {range_arr}")
# Linearly spaced values
linspace = np.linspace(0, 1, 5) # Start, stop, count
print(f"Linspace: {linspace}")
# Random arrays
random_arr = np.random.rand(3, 3) # Uniform [0, 1)
random_normal = np.random.randn(3, 3) # Standard normal
print(f"\nRandom:\n{random_arr}")1D Array: [1 2 3 4 5] Shape: (5,), Dtype: int64 2D Array: [[1 2 3] [4 5 6]] Shape: (2, 3) Zeros: [[0. 0. 0. 0.] [0. 0. 0. 0.] [0. 0. 0. 0.]] Range: [0 2 4 6 8] Linspace: [0. 0.25 0.5 0.75 1. ] Random: [[0.5488 0.7152 0.6028] [0.5449 0.4237 0.6459] [0.4376 0.8918 0.9637]]
NumPy supports vectorized operations - operations applied to entire arrays at once:
import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
# Element-wise operations
print(f"Addition: {a + b}")
print(f"Multiplication: {a * b}")
print(f"Power: {a ** 2}")
print(f"Square root: {np.sqrt(a)}")
# Comparison
print(f"\nGreater than 2: {a > 2}")
print(f"Values > 2: {a[a > 2]}")
# Aggregate functions
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(f"\nSum: {np.sum(arr)}")
print(f"Mean: {np.mean(arr)}")
print(f"Max: {np.max(arr)}")
print(f"Min: {np.min(arr)}")
# Along axis
print(f"Sum by column: {np.sum(arr, axis=0)}")
print(f"Sum by row: {np.sum(arr, axis=1)}")Addition: [ 6 8 10 12] Multiplication: [ 5 12 21 32] Power: [ 1 4 9 16] Square root: [1. 1.41421356 1.73205081 2. ] Greater than 2: [False False True True] Values > 2: [3 4] Sum: 21 Mean: 3.5 Max: 6 Min: 1 Sum by column: [5 7 9] Sum by row: [ 6 15]
Access and manipulate array elements:
import numpy as np
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# Indexing
print(f"First element: {arr[0]}")
print(f"Last element: {arr[-1]}")
# Slicing [start:stop:step]
print(f"First 5: {arr[:5]}")
print(f"Last 3: {arr[-3:]}")
print(f"Every 2nd: {arr[::2]}")
print(f"Reverse: {arr[::-1]}")
# 2D indexing
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(f"\n2D Array:\n{arr2d}")
print(f"Element at [1, 2]: {arr2d[1, 2]}")
print(f"First row: {arr2d[0, :]}")
print(f"Last column: {arr2d[:, -1]}")
# Boolean indexing
mask = arr2d > 5
print(f"\nMask:\n{mask}")
print(f"Values > 5: {arr2d[mask]}")First element: 0 Last element: 9 First 5: [0 1 2 3 4] Last 3: [7 8 9] Every 2nd: [0 2 4 6 8] Reverse: [9 8 7 6 5 4 3 2 1 0] 2D Array: [[1 2 3] [4 5 6] [7 8 9]] Element at [1, 2]: 6 First row: [1 2 3] Last column: [3 6 9] Mask: [[False False False] [False False True] [ True True True]] Values > 5: [6 7 8 9]
Change array dimensions while preserving data:
import numpy as np
arr = np.arange(12)
print(f"Original: {arr}")
print(f"Shape: {arr.shape}")
# Reshape
reshaped = arr.reshape(3, 4)
print(f"\nReshaped (3x4):\n{reshaped}")
# Transpose
transposed = reshaped.T
print(f"\nTransposed (4x3):\n{transposed}")
# Flatten
flattened = reshaped.flatten()
print(f"\nFlattened: {flattened}")
# Add/remove dimensions
expanded = arr[np.newaxis, :] # Add row dimension
print(f"\nExpanded shape: {expanded.shape}")
squeezed = expanded.squeeze() # Remove size-1 dimensions
print(f"Squeezed shape: {squeezed.shape}")Original: [ 0 1 2 3 4 5 6 7 8 9 10 11] Shape: (12,) Reshaped (3x4): [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] Transposed (4x3): [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]] Flattened: [ 0 1 2 3 4 5 6 7 8 9 10 11] Expanded shape: (1, 12) Squeezed shape: (12,)
Linear algebra operations essential for machine learning:
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(f"Matrix A:\n{A}")
print(f"\nMatrix B:\n{B}")
# Matrix multiplication
C = np.dot(A, B) # or A @ B
print(f"\nA @ B:\n{C}")
# Element-wise multiplication
element_wise = A * B
print(f"\nElement-wise A * B:\n{element_wise}")
# Transpose
print(f"\nA.T:\n{A.T}")
# Determinant
det = np.linalg.det(A)
print(f"\nDeterminant of A: {det}")
# Inverse
inv = np.linalg.inv(A)
print(f"\nInverse of A:\n{inv}")
# Verify: A @ A^-1 = I
identity = A @ inv
print(f"\nA @ A^-1 (should be I):\n{identity}")Matrix A: [[1 2] [3 4]] Matrix B: [[5 6] [7 8]] A @ B: [[19 22] [43 50]] Element-wise A * B: [[ 5 12] [21 32]] A.T: [[1 3] [2 4]] Determinant of A: -2.0 Inverse of A: [[-2. 1. ] [ 1.5 -0.5]] A @ A^-1 (should be I): [[1.0000000e+00 0.0000000e+00] [8.8817842e-16 1.0000000e+00]]
Try these exercises to test your understanding:
# Exercise 1: Create a 5x5 matrix with values ranging from 0 to 24
# Your code here:
matrix = np.arange(25).reshape(5, 5)
# Exercise 2: Extract all values from matrix that are divisible by 3
# Your code here:
divisible_by_3 = matrix[matrix % 3 == 0]
# Exercise 3: Create a 3x3 identity matrix
# Your code here:
identity = np.eye(3)
# Exercise 4: Calculate mean of each row in the matrix
# Your code here:
row_means = np.mean(matrix, axis=1)
# Exercise 5: Normalize the matrix (subtract mean, divide by std)
# Your code here:
normalized = (matrix - np.mean(matrix)) / np.std(matrix)
print("Check your answers below!")Matrix: [[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14] [15 16 17 18 19] [20 21 22 23 24]] Divisible by 3: [ 0 3 6 9 12 15 18 21 24] Identity: [[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]] Row means: [ 2. 7. 12. 17. 22.] Normalized matrix (first row): [-1.61 -1.48 -1.35 -1.22 -1.08]