Broadcasting

Broadcasting is a powerful mechanism that allows numpy to work with arrays of different shapes when performing arithmetic operations.

Broadcasting solves the problem of arithmetic between arrays of differing shapes by in effect replicating the smaller array along the last mismatched dimension.

import numpy as np

NumPy operations are usually done on pairs of arrays on an element-by-element basis. In the simplest case, the two arrays must have exactly the same shape, as in the following example:

a = np.array([1,2,3,4,5])
b = np.array([10,10,10,10,10])
a * b
array([10, 20, 30, 40, 50])

If the dimensions of two arrays are dissimilar, element-to-element operations are not possible. However, operations on arrays of non-similar shapes is still possible in NumPy, because of the broadcasting capability. The smaller array is broadcast to the size of the larger array so that they have compatible shapes.

Scalar and One-Dimensional Array

A single value or scalar can be used in arithmetic with a one-dimensional array.

c = 10
a * c
array([10, 20, 30, 40, 50])

The result is equivalent to the previous example where b was an array. We can think of the scalar c being stretched during the arithmetic operation into an array with the same shape as a. The new elements in c are simply copies of the original scalar.

Scalar and n-Dimensional Array

A scalar value can be used in arithmetic with a n-dimensional array.

one = np.ones((4,3))
one * c
array([[10., 10., 10.],
       [10., 10., 10.],
       [10., 10., 10.],
       [10., 10., 10.]])

One-Dimensional and n-Dimensional Arrays

A one-dimensional array can be used in arithmetic with a n-dimensional array.

Consider the following example: We have the heights (in cm) and weights ( in pounds) of a group of students. We store this information in an array called student_bio.

  • Heights are in cm

  • Weights are in kgs

heights  = [165,170,168,183,172,169]
weights  = [61,76,56,81,62,60]
student_bio = np.array([heights,weights])
student_bio
array([[165, 170, 168, 183, 172, 169],
       [ 61,  71,  56,  79,  62,  60]])

Now, we would like to convert heights into feet and weights into kilograms, for that the conversion factors are 0.0328084 and 2.20462 respectively

factor_1 = np.array([0.0328084,2.20462 ])
factor_1
array([0.0328084, 2.20462  ])
factor_1.shape
(2,)
student_bio.shape
(2, 6)

General Broadcasting Rules

When operating on two arrays, NumPy compares their shapes element-wise. The dimensions are considered in reverse order, starting with the trailing dimensions, and working its way forward. Two dimensions are compatible when

  1. they are equal,

  2. one of them is of size 1

Shape mismatch

This fails because there is a mismatch in the trailing dimensions
student bio: 2 x 6
factor_1:            2

The trailing dimensions here are 6 and 2, so there is a mismatch

student_bio * factor_1
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-15-55988f53db6d> in <module>()
----> 1 student_bio * factor_1

ValueError: operands could not be broadcast together with shapes (2,6) (2,) 
factor_2 = np.array([[0.0328084],[2.20462 ]])
factor_2
array([[0.0328084],
       [2.20462  ]])
factor_2.shape
(2, 1)

Dimensions match

The dimensions are:
2 x 6
2 x 1

Here, the last dimensions are 6,1 so they match on account of one of them being 1
The next dimensions are 2,2 so there is a match

student_bio * factor_2
array([[  5.413386 ,   5.577428 ,   5.5118112,   6.0039372,   5.6430448,
          5.5446196],
       [134.48182  , 156.52802  , 123.45872  , 174.16498  , 136.68644  ,
        132.2772   ]])

Why did we encounter an error for the first try?

Broadcasting is possible only when certain rules are satisfied, it does not work for all cases, and imposes a strict rule that must be satisfied for broadcasting to be performed.

The dimensions with size 1 are stretched or “copied” to match the other.

After application of the broadcasting rules, the sizes of all arrays must match.

In the above example, factor is stretched to match with the dimensions of students_bio in order to carry out operations.