Broadcasting in NumPy Arrays
Ease of array arithmetic and manipulation is one of the primary reasons to use Numpy.
Any two arrays that of the same shape can be added by applying the matrix addition rules.
Here is an example of adding two arrays having the same shape of 1x3
import numpy as np
a = np.array([3, 4, 5])
b = np.array([1, 2, 3])
print(a + b)
Output:
[4 6 8]
The above operation is straightforward enough for any student who is exposed to matrix addition. However if the two matrices are of different shapes then the standard matrix operations cannot be applied. This is where Numpy broadcasting comes to our rescue! The term broadcasting describes how NumPy treats and performs arithmetic operations on arrays with different shapes. By using broadcasting, you can completely eliminate the typical for loops that you would otherwise used to get the same output. Refer: https://numpy.org/doc/stable/user/basics.broadcasting.html
Using broadcasting any array can be participate in an arithmetic operation with a single number scalar or vector. However there are certain rules for the permissible size of the vector. Here are some examples:
Add a scalar to all the elements of an array
Scalar multiplication/division is a well known concept in mathematics where a given number is multiplied to or divided by, on all elements of a vector ( a.k.a array or matrix). However there is no such straight forward concept for scalar addition and subtraction on all elements of an array. Numpy library provides us a cool way of not only applying scalar multiplication but also for other mathematical operations of addition and subtraction.
In the below example, you add a single number 100 to all elements of the array.
import numpy as np
a = np.array([1, 2, 3])
a += 100 # Adds 100 to every element of a
print(a)
Output:
[101 102 103]
Conceptually from matrix addition standpoint, it appears as though if a 1xn matrix is used to add the number 100, then another matrix which is nx1 is created with the number 100 as all its element, and then added to the 1xn matrix. Although in reality Numpy uses efficient algorithms to provide this effect and it really does not create another matrix but the end result of the Numpy algorithm matches such a matrix addition. The addition operation used in the above example can be replaced with any of the other arithmetic operators (multiplication, division and subtraction) and they all work with the specific operator applied to every element of the array and the scalar.
Add a vector
If you want to add a vector (1-d array of numbers) to a 2 dimensional array 'b' then the vector size should match the number of columns of the array 'b' else an exception is thrown. Here is an example:
import numpy as np
b = np.array([
[4, 5, 6],
[7, 8, 9]
])
# Adds 100 to the 1st column of all rows. 200 to 2nd column and 300 to the 3rd column
b += [100, 200, 300]
print(b)
Output: [[104 205 306] [107 208 309]]
Note array 'b' of shape 2x3 is added to a vector of size 3. This is a requirement for broadcasting to work.
Broadcasting rules
When operating on two arrays, NumPy compares their shapes element-wise. Two dimensions are compatible for broadcasting when
- They are equal, or
- one of them is 1
If these conditions are not met, a ValueError: frames are not aligned exception is thrown. The size of the resulting array is the maximum size along each dimension of the input arrays.
Note that you can always add additional axes with '1' being the default shape value for the new axis. A vector of 1-D can be made 2-D, 3-D etc., by simply adding 1 for the new axis size. Here are some examples
import numpy as np
x = np.array([2,4,5])
print('original', x.shape)
x.shape = (1,3)
print('shape=1,3', x)
x.shape = (3,1)
print('shape=3,1', x)
x.shape = (1, 1, 3)
print('shape=1,1,3', x)
Output:
original (3,) shape=1,3 [[2 4 5]] shape=3,1 [[2] [4] [5]] shape=1,1,3 [[[2 4 5]]]
All the above creates a multidimensional array without any issues. When you are trying to broadcast with arrays of different sizes, this strategy of adding additional axes to make one of them '1', might help you figure out a way of solving it.
Here are some more examples of broadcasting:
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a + b) # New array which is the sum of a + b - added element wise
print(a * 3) # New array with each element of 'a' multiplied by 3
print(a ** 3) # New array with each element is an exponent 3 of a
print (a) # a is not changed with any of the operations
Output:
[5 7 9] [3 6 9] [ 1 8 27] [1 2 3]
You can use a Boolean array to filter out elements
np.array([1,2,3]) * [True, False, True]
Output:
array([1, 0, 3])
Reference
- You can find more examples here: https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html
Pure Matrix Operations
If broadcasting operation is not what you are looking for and instead you want pure matrix operations, then you can create a matrix using np.matrix and here is an example:
a = np.matrix(np.reshape(np.arange(0, 12), (3, 4)))
b = np.ones((4, 1))
a*b
Output>
matrix([[ 6.], [22.], [38.]])
NumPy arrays are used heavily in machine learning, especially in deep learning neural networks associated with image recognition, speech recognition etc.. However for Exploratory Data Analytics (EDA), we use Pandas DataFrame more often than NumPy arrays. In the next lesson you will learn about Pandas module.