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.
Mental Model
np.newaxis is just None used inside square brackets -- it tells NumPy "insert a length-1 axis here." Picture it as stretching a 1D ruler into a 2D sheet by adding a direction. Unlike expand_dims, you place it directly in the indexing expression, making it concise for inline broadcasting.
python
import numpy as np
What is np.newaxis?¶
np.newaxis is simply an alias for None:
python
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¶
```python 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¶
```python 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:
```python 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¶
```python 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¶
```python
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¶
```python 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¶
```python 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¶
```python 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¶
```python
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¶
```python
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:
```python 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 |
```python
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:
```python 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¶
```python 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
Exercises¶
Exercise 1.
Given a = np.array([2, 4, 6]), use np.newaxis to reshape it into a column vector of shape (3, 1). Then multiply it with b = np.array([1, 10, 100]) (shape (3,)) using broadcasting to produce a (3, 3) outer product. Print the result.
Solution to Exercise 1
import numpy as np
a = np.array([2, 4, 6])
b = np.array([1, 10, 100])
col = a[:, np.newaxis] # shape (3, 1)
result = col * b # broadcasting: (3, 1) * (3,) -> (3, 3)
print(result)
# [[ 2 20 200]
# [ 4 40 400]
# [ 6 60 600]]
Exercise 2.
Create a 1D array x = np.linspace(0, 1, 5). Use None (equivalent to np.newaxis) to compute the pairwise absolute difference matrix |x_i - x_j| for all pairs (i, j). The result should have shape (5, 5).
Solution to Exercise 2
import numpy as np
x = np.linspace(0, 1, 5)
# x[:, None] has shape (5, 1), x[None, :] has shape (1, 5)
diff_matrix = np.abs(x[:, None] - x[None, :])
print(diff_matrix.shape) # (5, 5)
print(diff_matrix)
Exercise 3.
Given a 2D array a = np.arange(6).reshape(2, 3), add a new axis using np.newaxis so that the result has shape (2, 1, 3). Then broadcast-add this with b = np.ones((4, 3)) to produce a result of shape (2, 4, 3). Print the shape of the result.
Solution to Exercise 3
import numpy as np
a = np.arange(6).reshape(2, 3)
a_expanded = a[:, np.newaxis, :] # shape (2, 1, 3)
b = np.ones((4, 3))
result = a_expanded + b # (2, 1, 3) + (4, 3) -> (2, 4, 3)
print(result.shape) # (2, 4, 3)