This tutorial covers advanced NumPy features that can elevate your data manipulation and analysis skills. Each example includes code and a detailed explanation, followed by an analysis of the results.
1. Broadcasting
Broadcasting allows you to perform arithmetic operations on arrays of different shapes.
Example: Element-wise Operations on Arrays with Different Shapes
import numpy as np
# Define arrays of different shapes
a = np.array([[1], [2], [3]]) # Shape (3, 1)
b = np.array([10, 20, 30]) # Shape (3,)
# Broadcasting operation
result = a * b
print("Array 'a':\n", a)
print("Array 'b':\n", b)
print("Result of Broadcasting:\n", result)
Array 'a': [[1] [2] [3]] Array 'b': [10 20 30] Result of Broadcasting: [[10 20 30] [20 40 60] [30 60 90]]
Analysis:
The smaller array b is broadcasted to match the shape of a.
Each row in a is multiplied by the corresponding element in b.
2. Vectorized Functions
NumPy allows element-wise operations on arrays using vectorized functions, which are faster than Python loops.
Example: Compute Sigmoid Function for an Array
# Sigmoid function
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# Generate data
x = np.linspace(-10, 10, 100)
y = sigmoid(x)
print("Input Array 'x':\n", x[:10]) # Print the first 10 elements
print("Sigmoid Output 'y':\n", y[:10]) # Print the first 10 elements
Input Array 'x': [-10. -9.7979798 -9.5959596 -9.39393939 -9.19191919 -8.98989899 -8.78787879 -8.58585859 -8.38383838 -8.18181818] Sigmoid Output 'y': [4.53978687e-05 5.55606489e-05 6.79983174e-05 8.32200197e-05 1.01848815e-04 1.24647146e-04 1.52547986e-04 1.86692945e-04 2.28478855e-04 2.79614739e-04]
3. Fancy Indexing
Fancy indexing lets you select elements from an array using another array of indices.
Example: Extract Specific Rows and Columns
# Define a 2D array
arr = np.arange(1, 17).reshape(4, 4) # Shape (4, 4)
# Select rows 1 and 3, and columns 0 and 2
rows = np.array([1, 3])
cols = np.array([0, 2])
selected = arr[rows[:, None], cols]
print("Original Array:\n", arr)
print("Selected Elements:\n", selected)
Original Array: [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12] [13 14 15 16]] Selected Elements: [[ 5 7] [13 15]]
4. Masking and Conditional Operations
Example: Filter Values Based on a Condition
# Generate random data
data = np.random.randint(0, 100, size=(10,))
# Create a mask for values greater than 50
mask = data > 50
# Apply the mask
filtered_data = data[mask]
print("Original Data:\n", data)
print("Filtered Data (> 50):\n", filtered_data)
Original Data: [60 86 30 75 26 87 4 21 8 92] Filtered Data (> 50): [60 86 75 87 92]
5.Statistical Functions
Example: Compute Descriptive Statistics
# Generate random data
data = np.random.normal(loc=0, scale=1, size=1000)
# Compute statistics
mean = np.mean(data)
std = np.std(data)
percentiles = np.percentile(data, [25, 50, 75])
print("Mean:", mean)
print("Standard Deviation:", std)
print("25th, 50th, 75th Percentiles:", percentiles)
Mean: -0.09316968744885226 Standard Deviation: 0.9904478322803227 25th, 50th, 75th Percentiles: [-0.76023323 -0.11687292 0.58894539]
6. Generating a 2D Mesh Grid
A mesh grid is a grid of coordinates that spans a given range. We’ll create a 2D mesh grid to analyze spatial data.
import numpy as np
import matplotlib.pyplot as plt
# Define grid parameters
x = np.linspace(-5, 5, 200) # 200 points from -5 to 5
y = np.linspace(-5, 5, 200)
# Create a 2D mesh grid
X, Y = np.meshgrid(x, y)
print("Shape of X:", X.shape)
print("Shape of Y:", Y.shape)
Shape of X: (200, 200) Shape of Y: (200, 200)
The mesh grid spans from¶
−
5
−5 to
5
5 along both axes with 200 points each, creating a 200×200 grid.
7.Applying a Gaussian (Normal) Distribution Function
We’ll compute a 2D Gaussian distribution over the mesh grid.
# Define a Gaussian function
def gaussian_2d(x, y, sigma_x=1.0, sigma_y=1.0, mu_x=0.0, mu_y=0.0):
return np.exp(-((x - mu_x)**2 / (2 * sigma_x**2) + (y - mu_y)**2 / (2 * sigma_y**2)))
# Apply the Gaussian function to the grid
Z = gaussian_2d(X, Y, sigma_x=1.5, sigma_y=1.0, mu_x=0, mu_y=0)
# Plot the Gaussian distribution
plt.figure(figsize=(8, 6))
plt.contourf(X, Y, Z, levels=50, cmap='viridis')
plt.colorbar(label='Gaussian Value')
plt.title("2D Gaussian Distribution")
plt.xlabel("X")
plt.ylabel("Y")
plt.show()
8. Adding Noise and Filtering
Add noise to the data and apply a Gaussian filter to smooth it.
from scipy.ndimage import gaussian_filter
# Add random noise to the Gaussian distribution
noise = np.random.normal(0, 0.1, Z.shape)
Z_noisy = Z + noise
# Apply a Gaussian filter to smooth the noisy data
Z_smooth = gaussian_filter(Z_noisy, sigma=1)
# Plot the noisy and smoothed data
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
axes[0].contourf(X, Y, Z_noisy, levels=50, cmap='coolwarm')
axes[0].set_title("Noisy Gaussian")
axes[1].contourf(X, Y, Z_smooth, levels=50, cmap='coolwarm')
axes[1].set_title("Smoothed Gaussian")
plt.show()
9. Spatial Gradients
Compute the spatial gradients (∂x/
∂Z,
∂y/
∂Z)
# Compute gradients along x and y directions
grad_x, grad_y = np.gradient(Z_smooth)
# Visualize the gradients
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
axes[0].contourf(X, Y, grad_x, levels=50, cmap='plasma')
axes[0].set_title("Gradient Along X")
axes[1].contourf(X, Y, grad_y, levels=50, cmap='plasma')
axes[1].set_title("Gradient Along Y")
plt.show()