NumPy Broadcasting: Operate on Arrays of Different Shapes
You've already seen that np.array([1,2,3]) * 2 multiplies every element by 2. But have you wondered how NumPy knows to stretch that single number 2 across the entire array? That mechanism is called broadcasting.
Broadcasting is NumPy's set of rules for operating on arrays with different shapes. It lets you add a single row to every row of a matrix, or subtract column means without writing a single loop. Once you understand it, you'll write cleaner and faster code.
In this tutorial, you'll learn the three broadcasting rules, how shape compatibility works, practical patterns for centering and scaling data, and how to debug shape mismatches.
What Is Broadcasting?
Broadcasting is how NumPy handles operations between arrays of different shapes. Instead of requiring you to manually duplicate data to make shapes match, NumPy "stretches" the smaller array virtually — without actually copying memory.
In the second example, the row [10, 20, 30] has shape (3,) and the matrix has shape (2, 3). NumPy conceptually repeats the row to create a (2, 3) array, then adds element-wise. No actual memory duplication happens — it's just smart indexing.
What Are the Three Broadcasting Rules?
NumPy follows three rules (checked in order) to determine if two shapes are compatible for broadcasting:
Rule 1: If the arrays have different numbers of dimensions, the shape of the smaller array is padded with 1s on the left side.
Rule 2: Arrays with a size of 1 along a particular dimension act as if they had the size of the larger array in that dimension.
Rule 3: If shapes disagree along any dimension and neither is 1, broadcasting fails with an error.
Let's trace through a more complex example. A shape (4, 1) array and a shape (3,) array:
When Does Broadcasting Fail?
Broadcasting fails when two dimensions disagree and neither is 1. For example, shapes (3,) and (4,) are incompatible — 3 and 4 are different and neither is 1.
How Do You Use Broadcasting in Practice?
The two most common real-world uses of broadcasting are centering data (subtracting the mean of each column) and scaling data (dividing by the standard deviation). These are fundamental steps in data preprocessing.
Notice how scores - col_means works without any loops. The column means array has shape (3,), which broadcasts against (4, 3) by stretching across all 4 rows. This is the standard way to z-score normalize data in machine learning.
Quick Reference: Shape Compatibility
Here are common broadcasting patterns you'll encounter:
Practice Exercises
Given an array of temperatures in Celsius celsius = np.array([0, 20, 37, 100]), convert them all to Fahrenheit using the formula F = C * 9/5 + 32. Print the result.
A teacher has a 3x4 grades matrix and wants to add different bonus points to each exam (column). The bonus array is [5, 3, 8, 2]. Use broadcasting to add the bonus to all students at once. Print the result.
grades = np.array([[70, 85, 60, 90],
[80, 75, 85, 70],
[90, 95, 70, 80]])
bonus = np.array([5, 3, 8, 2])Given the matrix below, subtract each row's mean from that row (center each row). You'll need np.newaxis or .reshape(-1, 1) to make the shapes compatible. Print the centered matrix.
data = np.array([[10, 20, 30],
[40, 50, 60],
[70, 80, 90]])What does the following code print? Trace through the broadcasting rules carefully.
import numpy as np
a = np.ones((4, 1))
b = np.ones((1, 3))
c = a + b
print(c.shape)
print(c)Use broadcasting to create a 5x5 multiplication table for numbers 1 through 5. The result should be a 5x5 array where element [i, j] equals (i+1) * (j+1). Print it.
Hint: create a column vector and a row vector, then multiply them.