Broadcasting
We have studied vectorized operations in the earlier section. The two main methods to perform vectorized operations are:
- to use Numpy’s universal functions (ufunc), as we have covered earlier, and,
- to use NumPy’s broadcasting feature, we will discuss here
Broadcasting is a set of rules for applying binary ufuncs (e.g., addition, subtraction, multiplication, division, etc.) on arrays of different sizes
We will go through some basic examples to revise the concept of broadcasting, covered in earlier sections.
First, Let suppose, we want to add two arrays having identical shape and none of the arrays need to be stretched to do the operation
import numpy as np
# creating arrays
ar1 = np.arange(1,4)
ar2 = np.arange(4,7)
print(f"ar1: {ar1}");print(f"ar2: {ar2}")
# adding two arrays using "+" operations
print(f"ar1 + ar2: {ar1+ar2}")
ar1: [1 2 3]
ar2: [4 5 6]
ar1 + ar2: [5 7 9]
When the arrays don’t have an identical shape, broadcasting rules will be applied to figure out how the shape of arrays are adjusted:
- 1.Rule 1: If the two arrays differ in their number of dimensions, the shape of the one with fewer dimensions is adjusted by adding
1
to the left side of itsshape
- 2.Rule 2: If the shape of the two arrays does not match in any dimension, the array with
shape
equal to1
in that dimension is stretched to match theshape
of other array
If even after applying the above two rules, the shapes of array can’t be adjusted,
ValueError
will be raisedLet’s study few cases, where these rules will be applied
Let suppose, we want to add a scalar
10
to the array ar1
.To broadcast, scalar of size 1 will be stretched to be size ofar1
.
It is mental equivalent to add
[10,10,10]
to [1,2,3]
in the example below.print(f"ar1: {ar1}")
print(f"ar1+ 10: {ar1 + 10}")
ar1: [1 2 3]
ar1+ 10: [11 12 13]
In this case, we will add 1D array
ar1
of size 3 to 2D array ar3
of size 9.To broadcast, arrayar1
will be stretched to be size ofar3
.
See the code below to understand the concept:
ar3 = np.zeros((3,3))
print(f"ar1: \n{ar1}\nar1 Shape:\n{ar1.shape}")
print(f"\nar3: \n{ar3}\nar3 Shape:\n{ar3.shape}")
# adding two arrays
print(f"\nar1 + ar3: \n{ar1+ar3}")
ar1:
[1 2 3]
ar1 Shape:
(3,)
ar3:
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
ar3 Shape:
(3, 3)
ar1 + ar3:
[[1. 2. 3.]
[1. 2. 3.]
[1. 2. 3.]]
How broadcasting rules are applied:
- According to rule 1, shape of
ar1
will be adjusted by adding1
on left.ar1
shape:(3,)
→(1,3)
- According to rule 2, shape of
ar1
will be adjusted to match the shape ofar2
, along the axis wherear1
has value of 1.ar1
shape:(1,3)
→(3,3)
to match withar2
shape of(3,3)
In this case, we will add 1D array
ar1
of size 3 to 2D array ar4
of size 3.To broadcast, both arraysar1
andar4
will be stretched.
See the code below to understand the concept:
ar4 = np.arange(1,4).reshape(3,1)
print(f"ar1: \n{ar1}\nar1 Shape:\n{ar1.shape}")
print(f"\nar4: \n{ar4}\nar4 Shape:\n{ar4.shape}")
print(f"\nar1 + ar4: \n{ar1 + ar4}")
ar1:
[1 2 3]
ar1 Shape:
(3,)
ar4:
[[1]
[2]
[3]]
ar4 Shape:
(3, 1)
ar1 + ar4:
[[2 3 4]
[3 4 5]
[4 5 6]]
How broadcasting rules are applied:
- According to rule 1, shape of
ar1
will be adjusted by adding1
on left.ar1
shape:(3,)
-->(1,3)
- According to rule 2, shape of both
ar1
andar4
will be adjusted along the axis where they have value of 1.ar1
shape:(1,3)
-->(3,3)
to match withar4
shape of(3,1)
ar4
shape:(3,1)
-->(3,3)
to match withar1
shape of(1,3)
In this example, we will discuss the case that leads to
ValueError
because even after applying both rules of broadcasting, the arrays shape doesn’t matchar5 = np.arange(6).reshape(3,2)
print(f"ar1: \n{ar1}\nar1 Shape:\n{ar1.shape}")
print(f"\nar5: \n{ar5}\nar5 Shape:\n{ar5.shape}")
# add ar1 and ar5
print(ar1+ar5)
ar1:
[1 2 3]
ar1 Shape:
(3,)
ar5:
[[0 1]
[2 3]
[4 5]]
ar5 Shape:
(3, 2)
ValueError: operands could not be broadcast together with shapes (3,) (3,2)
How broadcasting rules are applied:
- According to rule 1, shape of
ar1
will be adjusted by adding1
on left.ar1
shape:(3,)
-->(1,3)
- According to rule 2, shape of
ar1
will be adjusted to match the shape ofar5
, along the axis wherear1
has value of 1.ar1
shape:(1,3)
-->(3,3)
to match withar5
shape of(3,2)
- However, shapes of
ar1
,(3,3)
still doesn’t match with shape ofar5
,(3,2)
. This will raise an error
Last modified 4mo ago