Skip to content

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 (or None) 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