NumPy: Reshaping and Dimensions 🧱
The LEGO Brick Analogy
Imagine you have a box of LEGO bricks. You can arrange them in a single long line, stack them in a flat rectangle, or build a tall tower. The same bricks, just arranged differently!
NumPy arrays work exactly like this. You can reshape them—change how they’re organized—without changing the actual data inside.
1. Reshaping with reshape() 🔄
What is it?
reshape() lets you rearrange your array into a new shape. Think of it as taking your LEGO line and reorganizing it into rows and columns.
The Golden Rule: The total number of elements must stay the same!
import numpy as np
# 12 bricks in a line
bricks = np.array([1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12])
# Reshape into 3 rows, 4 columns
grid = bricks.reshape(3, 4)
print(grid)
Output:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
Why does this work? 12 bricks = 3 rows × 4 columns = 12. The math checks out!
graph TD A["[1,2,3,4,5,6,7,8,9,10,11,12]"] --> B["reshape#40;3,4#41;"] B --> C["3 rows × 4 columns"]
2. The Magic -1: Let NumPy Figure It Out 🧙♂️
What if you’re lazy? (We all are!)
Use -1 and NumPy will calculate that dimension for you.
# 12 elements, want 4 columns
# How many rows? Let NumPy decide!
result = bricks.reshape(-1, 4)
print(result.shape) # (3, 4)
# Want 3 rows, unknown columns?
result2 = bricks.reshape(3, -1)
print(result2.shape) # (3, 4)
Think of -1 as saying:
“Hey NumPy, you’re smart. Figure out this part for me!”
Important: You can only use ONE -1 per reshape. NumPy can solve for one unknown, not two!
3. Flattening Arrays: Back to a Line 📏
Sometimes you want to undo all that shaping and get back to a simple line of numbers.
Three Ways to Flatten:
| Method | Creates Copy? | Speed |
|---|---|---|
flatten() |
Yes (always) | Slower |
ravel() |
No (usually) | Faster |
reshape(-1) |
No (usually) | Fast |
grid = np.array([[1, 2, 3],
[4, 5, 6]])
# Method 1: flatten() - always a copy
flat1 = grid.flatten()
print(flat1) # [1 2 3 4 5 6]
# Method 2: ravel() - usually a view
flat2 = grid.ravel()
print(flat2) # [1 2 3 4 5 6]
# Method 3: reshape(-1)
flat3 = grid.reshape(-1)
print(flat3) # [1 2 3 4 5 6]
When to use what?
- Need a safe copy? Use
flatten() - Need speed? Use
ravel()orreshape(-1)
4. Transposing Arrays: Flip the Grid! 🔃
Transpose swaps rows and columns. What was a row becomes a column!
matrix = np.array([[1, 2, 3],
[4, 5, 6]])
print("Original shape:", matrix.shape)
# (2, 3) - 2 rows, 3 columns
transposed = matrix.T
print("Transposed shape:", transposed.shape)
# (3, 2) - 3 rows, 2 columns
print(transposed)
Output:
[[1 4]
[2 5]
[3 6]]
graph TD A["Original: 2×3"] --> B[".T"] B --> C["Transposed: 3×2"] D["Rows ↔ Columns"]
Three ways to transpose:
matrix.T # Shortcut
matrix.transpose() # Full method
np.transpose(matrix) # Function
5. Swapping and Moving Axes 🎯
For arrays with 3 or more dimensions, you might want to rearrange specific axes.
swapaxes() - Swap Two Axes
# 3D array: 2 layers, 3 rows, 4 columns
cube = np.arange(24).reshape(2, 3, 4)
print("Original:", cube.shape) # (2, 3, 4)
# Swap axis 0 and axis 2
swapped = cube.swapaxes(0, 2)
print("Swapped:", swapped.shape) # (4, 3, 2)
moveaxis() - Move One Axis to New Position
# Move axis 0 to position 2
moved = np.moveaxis(cube, 0, 2)
print("Moved:", moved.shape) # (3, 4, 2)
Real-world example:
Image data often comes as (batch, height, width, channels). Some libraries want (batch, channels, height, width). Use moveaxis to convert!
6. Adding Dimensions: Make It Bigger! 📦
Sometimes you need to add an extra dimension to your array. It’s like putting your LEGO creation in a box.
Method 1: np.newaxis
line = np.array([1, 2, 3])
print("Original:", line.shape) # (3,)
# Add dimension at start
row = line[np.newaxis, :]
print("Row vector:", row.shape) # (1, 3)
# Add dimension at end
column = line[:, np.newaxis]
print("Column vector:", column.shape) # (3, 1)
Method 2: np.expand_dims()
line = np.array([1, 2, 3])
# Add axis at position 0
expanded = np.expand_dims(line, axis=0)
print(expanded.shape) # (1, 3)
# Add axis at position 1
expanded2 = np.expand_dims(line, axis=1)
print(expanded2.shape) # (3, 1)
Why add dimensions?
- Broadcasting requires matching dimensions
- Neural networks expect specific input shapes
- Matrix multiplication rules
7. Squeeze: Remove Extra Dimensions 🧹
The opposite of adding dimensions! squeeze() removes dimensions that have size 1.
# Array with unnecessary dimensions
bulky = np.array([[[1, 2, 3]]])
print("Bulky shape:", bulky.shape) # (1, 1, 3)
# Remove all size-1 dimensions
slim = bulky.squeeze()
print("Slim shape:", slim.shape) # (3,)
# Remove specific axis
specific = np.squeeze(bulky, axis=0)
print("Specific:", specific.shape) # (1, 3)
graph TD A["#40;1, 1, 3#41;"] --> B["squeeze#40;#41;"] B --> C["#40;3,#41;"] D["Removes size-1 dims"]
Warning: squeeze() won’t remove dimensions larger than 1!
Quick Summary Table 📊
| Operation | What It Does | Example |
|---|---|---|
reshape(3,4) |
New shape | (12,) → (3,4) |
reshape(-1,4) |
Auto-calculate | NumPy finds rows |
flatten() |
To 1D (copy) | (3,4) → (12,) |
ravel() |
To 1D (view) | (3,4) → (12,) |
.T |
Transpose | (2,3) → (3,2) |
swapaxes(0,2) |
Swap axes | (2,3,4) → (4,3,2) |
moveaxis(0,2) |
Move axis | (2,3,4) → (3,4,2) |
newaxis |
Add dim | (3,) → (1,3) |
expand_dims |
Add dim | (3,) → (3,1) |
squeeze() |
Remove size-1 | (1,1,3) → (3,) |
The Big Picture 🎯
Think of your NumPy array as clay:
- Reshape = Mold it into different forms
- Flatten = Roll it back into a snake
- Transpose = Flip it over
- Swap/Move axes = Rotate in 3D space
- Add dimensions = Put it in a box
- Squeeze = Take it out of the box
The data stays the same. Only the organization changes!
Practice Challenge 🏆
Can you predict the output?
arr = np.arange(24)
result = arr.reshape(2, 3, -1)
print(result.shape)
Answer: (2, 3, 4) because 24 ÷ (2 × 3) = 4!
You now have the power to reshape any NumPy array. Go forth and mold your data! 🚀