np.newaxis — Adding Dimensions¶
np.newaxis inserts a new axis (dimension) into an array, increasing its dimensionality by one. This is essential for broadcasting and reshaping operations.
import numpy as np
What is np.newaxis?¶
np.newaxis is simply an alias for None:
print(np.newaxis is None) # True
When used in array indexing, it inserts a new axis of length 1.
Basic Usage¶
1D to 2D: Row Vector¶
arr = np.array([1, 2, 3, 4])
print(arr.shape) # (4,)
# Add axis at position 0 → row vector
row = arr[np.newaxis, :]
print(row.shape) # (1, 4)
print(row)
# [[1 2 3 4]]
1D to 2D: Column Vector¶
arr = np.array([1, 2, 3, 4])
# Add axis at position 1 → column vector
col = arr[:, np.newaxis]
print(col.shape) # (4, 1)
print(col)
# [[1]
# [2]
# [3]
# [4]]
Visual Explanation¶
Original: arr = [1, 2, 3, 4] shape: (4,)
arr[np.newaxis, :] shape: (1, 4)
┌─────────────────┐
│ [1, 2, 3, 4] │ ← 1 row, 4 columns
└─────────────────┘
arr[:, np.newaxis] shape: (4, 1)
┌───┐
│ 1 │ ← 4 rows, 1 column
│ 2 │
│ 3 │
│ 4 │
└───┘
Multiple Axes¶
Add multiple dimensions:
arr = np.array([1, 2, 3])
print(arr.shape) # (3,)
# Add two axes
expanded = arr[np.newaxis, :, np.newaxis]
print(expanded.shape) # (1, 3, 1)
# Equivalent to
expanded = arr[None, :, None]
Broadcasting with newaxis¶
The main use of newaxis is enabling broadcasting between arrays of different shapes.
Outer Product¶
a = np.array([1, 2, 3])
b = np.array([10, 20, 30, 40])
# Without newaxis: error or unexpected result
# a * b # shapes (3,) and (4,) don't broadcast
# With newaxis: outer product
result = a[:, np.newaxis] * b[np.newaxis, :]
# Shapes: (3, 1) * (1, 4) → (3, 4)
print(result)
# [[ 10 20 30 40]
# [ 20 40 60 80]
# [ 30 60 90 120]]
Row-wise Operations¶
# 2D array
matrix = np.array([[1, 2, 3],
[4, 5, 6]])
# 1D array to subtract from each row
row_values = np.array([1, 1, 1])
# Direct subtraction works (shapes align)
print(matrix - row_values)
# [[0 1 2]
# [3 4 5]]
Column-wise Operations¶
matrix = np.array([[1, 2, 3],
[4, 5, 6]])
# 1D array to subtract from each column
col_values = np.array([1, 2])
# Need newaxis to align shapes
# matrix shape: (2, 3)
# col_values shape: (2,) → need (2, 1)
print(matrix - col_values[:, np.newaxis])
# [[0 1 2]
# [2 3 4]]
Practical Examples¶
Normalize Each Column¶
data = np.array([[1, 100, 1000],
[2, 200, 2000],
[3, 300, 3000]])
# Compute column means and stds
col_mean = data.mean(axis=0) # shape (3,)
col_std = data.std(axis=0) # shape (3,)
# Normalize (broadcasting works directly)
normalized = (data - col_mean) / col_std
Normalize Each Row¶
data = np.array([[1, 2, 3],
[10, 20, 30],
[100, 200, 300]])
# Compute row means
row_mean = data.mean(axis=1) # shape (3,)
row_std = data.std(axis=1) # shape (3,)
# Need newaxis for broadcasting
normalized = (data - row_mean[:, np.newaxis]) / row_std[:, np.newaxis]
Distance Matrix¶
# Points in 2D
points = np.array([[0, 0],
[1, 0],
[0, 1],
[1, 1]]) # shape (4, 2)
# Compute pairwise distances
# Expand dimensions for broadcasting
diff = points[:, np.newaxis, :] - points[np.newaxis, :, :]
# Shape: (4, 1, 2) - (1, 4, 2) → (4, 4, 2)
distances = np.sqrt((diff ** 2).sum(axis=2))
print(distances)
# [[0. 1. 1. 1.414]
# [1. 0. 1.414 1. ]
# [1. 1.414 0. 1. ]
# [1.414 1. 1. 0. ]]
Image Channel Operations¶
# Grayscale image: (height, width)
gray = np.random.rand(100, 100)
# Convert to RGB by repeating across new channel axis
rgb = gray[:, :, np.newaxis] * np.array([1, 0.5, 0.5])
# Shape: (100, 100, 1) * (3,) → (100, 100, 3)
newaxis vs reshape vs expand_dims¶
Three ways to add dimensions:
arr = np.array([1, 2, 3, 4])
# Method 1: newaxis
result1 = arr[:, np.newaxis]
# Method 2: reshape
result2 = arr.reshape(-1, 1)
# Method 3: expand_dims
result3 = np.expand_dims(arr, axis=1)
# All produce shape (4, 1)
print(result1.shape, result2.shape, result3.shape)
When to Use Each¶
| Method | Best For |
|---|---|
np.newaxis |
Inline broadcasting, clear axis position |
reshape() |
Complex shape changes |
expand_dims() |
Programmatic axis insertion |
# newaxis: clear where axis is added
col = arr[:, np.newaxis] # Obviously adds axis at end
# expand_dims: when axis position is variable
axis = 1
col = np.expand_dims(arr, axis=axis)
# reshape: multiple changes at once
reshaped = arr.reshape(2, 2)
Using None Instead¶
Since np.newaxis is None, you can use None directly:
arr = np.array([1, 2, 3])
# These are equivalent:
arr[np.newaxis, :]
arr[None, :]
arr[:, np.newaxis]
arr[:, None]
np.newaxis is more readable and explicit; None is shorter.
Common Patterns¶
arr = np.array([1, 2, 3, 4])
# Row vector (1, n)
arr[np.newaxis, :]
arr[None, :]
arr.reshape(1, -1)
# Column vector (n, 1)
arr[:, np.newaxis]
arr[:, None]
arr.reshape(-1, 1)
# Add axis at beginning
arr[np.newaxis, ...] # ... means "all other axes"
# Add axis at end
arr[..., np.newaxis]
Summary¶
| Expression | Input Shape | Output Shape |
|---|---|---|
arr[np.newaxis, :] |
(n,) |
(1, n) |
arr[:, np.newaxis] |
(n,) |
(n, 1) |
arr[np.newaxis, :, np.newaxis] |
(n,) |
(1, n, 1) |
arr[:, np.newaxis, :] |
(m, n) |
(m, 1, n) |
Key Takeaways:
np.newaxis(orNone) inserts a new axis of length 1- Essential for broadcasting between arrays of different dimensions
- Use for outer products, row/column operations, distance matrices
- Position in index determines where axis is inserted
- Equivalent to
np.expand_dims()but more concise inline