Free preview
117 lessons
Essential Python for Data Science and ML
Free preview
Essential Python for Data Science and ML · 117 lessons
No surprise gaps
Actually remember it
Skip what you know
One subscription. All learning paths included.
Our content is best on a larger screen
What is broadcasting?
Broadcasting is the mechanism that lets NumPy perform element-wise operations on arrays of different shapes without copying data.
NumPy automatically "stretches" smaller arrays so they behave as if they had the same shape as the larger one.
Scalar broadcasting is the simplest case:
import numpy as np
arr = np.array([1, 2, 3, 4])
print(arr + 10) # [11 12 13 14]
Here, NumPy conceptually treated 10 as if it had been repeated four times - but behind the scenes, it never created [10, 10, 10, 10].
Array broadcasting works the same way. NumPy virtually lines up the shapes and stretches the smaller array as needed:
mat = np.array([[1, 2, 3],
[4, 5, 6]])
vec = np.array([10, 20, 30])
print(mat + vec)
[[11 22 33]
[14 25 36]]
The 1D array vec was stretched across each row of mat - no copying of data, no for loops.
Key Point
Broadcasting is NumPy's way of making different-shaped arrays compatible so that operations work element-wise without explicit repetition.
Rules of broadcasting
To understand what broadcasting can and cannot do, we need the rules.
NumPy compares array shapes dimension by dimension, starting from the last axis (rightmost).
If the shapes have different lengths, we conceptually pad the shorter shape with 1s on the left so the dimensions line up for comparison. (NumPy does not actually reshape the array - this is just how we reason about alignment.)
Key Point
Two dimensions are compatible if:
If all dimensions are compatible, broadcasting succeeds. Otherwise, it raises an error.
The resulting shape is the maximum size along each axis.
Tip
If this still feels abstract, that is fine - the key aim here is to get comfortable with the rules for checking compatibility. The next section grounds these rules in practical examples.
Let us now check broadcasting compatibility for a few array shape combinations.
Example 1: Array A has shape (5, 3) and array B has shape (3,)
A and B can be broadcast. Operations like A + B and A * B behave as if B were repeated across each of A's rows.
Details
Example 2: Array C has shape (4, 1, 6) and array D has shape (3, 6)
C and D can be broadcast. This effectively repeats D across the first axis of C.
Details
Example 3: Array E has shape (7, 5) and array F has shape (7, 4)
E and F cannot be broadcast. Any operation like E + F will raise a ValueError.
Details
Practice questions
4 questions
Suppose array X has shape (2, 1, 8) and array Y has shape (5, 8).
According to NumPy's broadcasting rules, can X and Y be broadcast together, and if so, what would be the resulting shape?
Select the correct answer:
+ 3 more questions
Applying broadcasting in practice
Let us now look at broadcasting in action with concrete arrays.
Example 1: 1D added to 2D
a = np.ones((2, 3))
b = np.array([10, 20, 30])
print(a + b)
[[11. 21. 31.]
[11. 21. 31.]]
Here b has shape (3,), which is padded to (1, 3) and stretched across both rows of a. The result has shape (2, 3).
Example 2: Outer sum (column + row)
c = np.array([[1],
[2],
[3]]) # shape (3, 1)
d = np.array([10, 20, 30]) # shape (3,)
print(c + d)
[[11 21 31]
[12 22 32]
[13 23 33]]
d of shape (3,) is padded to (1, 3). Comparing (3, 1) and (1, 3) - both axes have one side equal to 1, so broadcasting produces an outer sum with shape (3, 3).
Example 3: Incompatible case
e = np.ones((3, 2)) # shape (3, 2)
f = np.ones((4,)) # shape (4,)
print(e + f) # ValueError!
Why does this fail?
(4,) to (1, 4).(3, 2) vs (1, 4).(2 vs 4) - incompatible, because neither equals the other and neither is 1.Broadcasting fails and NumPy raises an error.
Practice questions
3 questions
A colour image can be represented as a 3D array of shape (height, width, channels).
In the Python Editor, a colour image is loaded into a NumPy array called flower.
Run the starter code to visualise it.
Task
intensity_factors to the flower array. Assign the result to a variable called transformed_flower.transformed_flower to an integer array using the .astype("int") method on the array, and reassign the result back to transformed_flower.
.astype() returns a new array, it does not convert in place.Once you have completed these steps, run the code. It will output a token used to verify your implementation.
What is the token?
Tip
If you want to visualise the transformed flower run:
plt.imshow(transformed_flower)
plt.show()
Select the correct answer:
+ 2 more questions
Using keepdims when broadcasting
When we reduce an array with operations like sum, mean, or max, NumPy removes the reduced axis. This often produces a result with fewer dimensions - for example, reducing a 2D array along rows gives a 1D vector.
In many workflows we need the reduced result to retain its shape context so it can broadcast back against the original array. This is where keepdims=True comes in - it tells NumPy to keep the reduced axes as size-1 dimensions, so the result stays broadcast-compatible.
Key Point
keepdims=True preserves each reduced axis as a length-1 dimension, making the result broadcast-ready.
Suppose we have a 2D array and want to divide each entry in a row by the sum of that row - a common step in data normalisation.
import numpy as np
array = np.array([[2, 2, 4],
[1, 5, 4]])
# Reduce along rows (axis=1), but keep dimensions
row_sums = np.sum(array, axis=1, keepdims=True)
print(row_sums.shape) # (2, 1)
print(row_sums)
# [[ 8]
# [10]]
# Broadcasts cleanly across rows
print(array / row_sums)
# [[0.25 0.25 0.5 ]
# [0.1 0.5 0.4 ]]
Here, row_sums has shape (2, 1). This pairs perfectly with the (2, 3) shape of array, so broadcasting divides each row by its own sum without any reshaping.
keepdims?Details
Row vs. column aggregations for 2D arrays
For a 2D array with shape (n, m), row sums without keepdims produce shape (n,), which pads to (1, n) and fails to align with (n, m). With keepdims=True we get (n, 1), which broadcasts cleanly.
Column sums do not have this problem - the result has shape (m,), which pads to (1, m) and is directly compatible with (n, m).
Practice questions
3 questions
Suppose an array arr has shape (6, 4, 5). What are the shapes of the following operations?
arr.sum(axis=0) → ?arr.sum(axis=2, keepdims=True) → ?arr.sum(axis=(0, 1), keepdims=True) → ?Choose the correct options below.
Select the correct answer:
+ 2 more questions