Python NumPy: How to Change NumPy Array Dimensions in Python
Reshaping arrays is fundamental for preparing data for machine learning models, matrix operations, and data transformations. NumPy provides several methods to reorganize array dimensions while preserving or modifying the underlying data.
Using reshape() - The Standard Approach
The reshape() method returns a new view of the array with a different shape. The total number of elements must remain constant.
import numpy as np
arr = np.arange(12)
print(f"Original shape: {arr.shape}")
# Reshape to 3 rows, 4 columns
reshaped = arr.reshape(3, 4)
print(f"New shape: {reshaped.shape}")
print(reshaped)
Output:
Original shape: (12,)
New shape: (3, 4)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
The -1 Shortcut for Auto-Calculation
Use -1 to let NumPy calculate one dimension automatically:
import numpy as np
arr = np.arange(12)
# Auto-calculate rows for 4 columns
result = arr.reshape(-1, 4)
print(result.shape) # (3, 4)
# Auto-calculate columns for 3 rows
result = arr.reshape(3, -1)
print(result.shape) # (3, 4)
# Convert to column vector
col_vector = arr.reshape(-1, 1)
print(col_vector.shape) # (12, 1)
Output:
(3, 4)
(3, 4)
(12, 1)
The -1 shortcut is especially useful when you know one dimension but the other depends on your data size-common in ML pipelines.
Shape Must Be Compatible
The total element count must match before and after reshaping:
import numpy as np
arr = np.arange(12) # 12 elements
# ✅ Valid: 3 × 4 = 12
arr.reshape(3, 4)
# ✅ Valid: 2 × 6 = 12
arr.reshape(2, 6)
# ✅ Valid: 2 × 2 × 3 = 12
arr.reshape(2, 2, 3)
# ❌ Invalid: 3 × 5 = 15 ≠ 12
try:
arr.reshape(3, 5)
except ValueError as e:
print(f"Error: {e}")
# Error: cannot reshape array of size 12 into shape (3,5)
Using resize() - Changes Element Count
Unlike reshape(), resize() can change the total number of elements by repeating or truncating data.
np.resize() Function (Repeats Data)
import numpy as np
arr = np.array([1, 2, 3])
# Expand: repeats elements to fill new shape
resized = np.resize(arr, (3, 3))
print(resized)
# [[1 2 3]
# [1 2 3]
# [1 2 3]]
# Expand to different shape
resized = np.resize(arr, (2, 5))
print(resized)
# [[1 2 3 1 2]
# [3 1 2 3 1]]
Output:
[[1 2 3]
[1 2 3]
[1 2 3]]
[[1 2 3 1 2]
[3 1 2 3 1]]
ndarray.resize() Method (Fills with Zeros)
The in-place method pads with zeros instead of repeating:
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
# In-place resize (modifies original, pads with zeros)
arr.resize((3, 4))
print(arr)
Output:
[[1 2 3 4]
[5 6 0 0]
[0 0 0 0]]
The in-place resize() method cannot be used if the array is referenced elsewhere. Use np.resize() function for safer operations.
Modifying .shape Directly (In-Place)
Assign a new shape tuple directly to the .shape attribute:
import numpy as np
arr = np.arange(6)
print(f"Before: {arr.shape}")
arr.shape = (2, 3)
print(f"After: {arr.shape}")
print(arr)
Output:
Before: (6,)
After: (2, 3)
[[0 1 2]
[3 4 5]]
This modifies the array in-place and has the same constraints as reshape().
Adding and Removing Dimensions
Adding Dimensions with np.newaxis
import numpy as np
arr = np.array([1, 2, 3])
print(f"Original: {arr.shape}") # (3,)
# Add dimension at the end (column vector)
col = arr[:, np.newaxis]
print(f"Column: {col.shape}") # (3, 1)
# Add dimension at the start (row vector)
row = arr[np.newaxis, :]
print(f"Row: {row.shape}") # (1, 3)
Output:
Original: (3,)
Column: (3, 1)
Row: (1, 3)
Adding Dimensions with expand_dims()
import numpy as np
arr = np.array([1, 2, 3])
# axis=0: add dimension at start
expanded = np.expand_dims(arr, axis=0)
print(expanded.shape) # (1, 3)
# axis=1: add dimension at position 1
expanded = np.expand_dims(arr, axis=1)
print(expanded.shape) # (3, 1)
# axis=-1: add dimension at end
expanded = np.expand_dims(arr, axis=-1)
print(expanded.shape) # (3, 1)
Output:
(1, 3)
(3, 1)
(3, 1)
Removing Dimensions with squeeze()
Remove dimensions of size 1:
import numpy as np
arr = np.array([[[1, 2, 3]]])
print(f"Before: {arr.shape}") # (1, 1, 3)
squeezed = arr.squeeze()
print(f"After: {squeezed.shape}") # (3,)
# Remove specific axis only
arr = np.zeros((1, 3, 1))
print(np.squeeze(arr, axis=0).shape) # (3, 1)
print(np.squeeze(arr, axis=2).shape) # (1, 3)
Output:
Before: (1, 1, 3)
After: (3,)
(3, 1)
(1, 3)
Flattening Arrays
Convert multi-dimensional arrays back to 1D:
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
# flatten() returns a copy
flat = arr.flatten()
print(flat) # [1 2 3 4 5 6]
# ravel() returns a view (more memory efficient)
raveled = arr.ravel()
print(raveled) # [1 2 3 4 5 6]
# reshape(-1) also flattens
flattened = arr.reshape(-1)
print(flattened) # [1 2 3 4 5 6]
Output:
[1 2 3 4 5 6]
[1 2 3 4 5 6]
[1 2 3 4 5 6]
Use ravel() for better performance when you don't need a copy. Use flatten() when you need to modify the result without affecting the original.
Transposing Arrays
Swap dimensions using transpose:
import numpy as np
arr = np.arange(6).reshape(2, 3)
print(f"Original shape: {arr.shape}") # (2, 3)
print(arr)
# [[0 1 2]
# [3 4 5]]
# Transpose swaps rows and columns
transposed = arr.T
print(f"Transposed shape: {transposed.shape}") # (3, 2)
print(transposed)
# [[0 3]
# [1 4]
# [2 5]]
# For higher dimensions, specify axis order
arr_3d = np.arange(24).reshape(2, 3, 4)
reordered = arr_3d.transpose(1, 0, 2)
print(reordered.shape) # (3, 2, 4)
Output:
Original shape: (2, 3)
[[0 1 2]
[3 4 5]]
Transposed shape: (3, 2)
[[0 3]
[1 4]
[2 5]]
(3, 2, 4)
Practical ML Examples
Preparing Image Data
import numpy as np
# Single grayscale image (28x28 pixels)
image = np.random.rand(28, 28)
# Add batch and channel dimensions for CNN
# Shape: (batch_size, height, width, channels)
cnn_input = image.reshape(1, 28, 28, 1)
print(f"CNN input shape: {cnn_input.shape}")
Output:
CNN input shape: (1, 28, 28, 1)
Reshaping for sklearn
import numpy as np
# Feature as 1D array
feature = np.array([1.5, 2.3, 3.1, 4.7, 5.2])
# sklearn expects 2D: (n_samples, n_features)
X = feature.reshape(-1, 1)
print(f"sklearn input shape: {X.shape}")
Output:
sklearn input shape: (5, 1)
Batch Processing
import numpy as np
# Flatten batch of images
batch = np.random.rand(32, 28, 28) # 32 images, 28x28 each
# Flatten each image to vector
flattened = batch.reshape(32, -1)
print(f"Flattened batch: {flattened.shape}") # (32, 784)
Output:
Flattened batch: (32, 784)
Method Comparison
| Method | Changes Element Count | In-Place | Returns |
|---|---|---|---|
reshape() | ❌ No | ❌ No | View |
np.resize() | ✅ Yes (repeats) | ❌ No | Copy |
arr.resize() | ✅ Yes (zeros) | ✅ Yes | None |
.shape = ... | ❌ No | ✅ Yes | N/A |
squeeze() | ❌ No | ❌ No | View |
expand_dims() | ❌ No | ❌ No | View |
flatten() | ❌ No | ❌ No | Copy |
ravel() | ❌ No | ❌ No | View |
Summary
- Use
reshape()for standard dimension changes-it's the most common and flexible method. - Use
-1to auto-calculate one dimension. - For adding single dimensions,
np.newaxisorexpand_dims()provide clear intent. - Use
np.resize()only when you need to change the total element count by repeating data.