Programming for Data Science¶

NumPy¶

Dr. Bhargavi R

SCOPE, VIT Chennai

Broadcasting¶

  • Broadcasting allows to work with arrays of different shapes when performing arithmetic operations.
In [1]:
import numpy as np

a = np.array([i for i in range(1,10)]).reshape(3,3)
b = [1, 1, 1]
In [2]:
print(a)
print(b)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
[1, 1, 1]
In [3]:
c = a + b     
print(c)        #Remember this Value!
[[ 2  3  4]
 [ 5  6  7]
 [ 8  9 10]]
In [4]:
# The above broadcasting is equivalent to the following

d = np.empty_like(a)
print(d)

for i in range(3):
    d[i , :] = a[i , : ] + b
    
print(d)
[[0 0 0]
 [0 0 0]
 [0 0 0]]
[[ 2  3  4]
 [ 5  6  7]
 [ 8  9 10]]
In [5]:
# The above broadcasting is also equivalent to the following

b_modified = np.tile(b, (3, 1))   # Stack 3 copies of b on top of each other
c          = a + b_modified  

print(b_modified)                 
print(c)  
[[1 1 1]
 [1 1 1]
 [1 1 1]]
[[ 2  3  4]
 [ 5  6  7]
 [ 8  9 10]]

Broadcasting Rules¶

Broadcasting follows a strict set of rules to determine the interaction between two arrays:

Rule 1: If the two arrays differ in their number of dimensions, the shape of the one with fewer dimensions is padded with ones on its leading (left) side.

Rule 2: If the shape of the two arrays does not match in any dimension, the array with shape equal to 1 in that dimension is stretched to match the other shape.

Rule 3: If in any dimension, the sizes disagree and neither is equal to 1, an error is raised.

In [6]:
M = np.ones((2, 3))
a = np.arange(3)
In [7]:
print(M)
[[1. 1. 1.]
 [1. 1. 1.]]
In [8]:
print(a)
[0 1 2]
In [9]:
print(M.shape)
print(a.shape)
(2, 3)
(3,)

We see by rule 1 that the array a has fewer dimensions, so we pad it on the left with ones:

M.shape = (2, 3)
a.shape = (1, 3)

By rule 2, we now see that the first dimension disagrees, so we stretch this dimension to match, and then two arrays can be added:

M.shape = (2, 3)
a.shape = (2, 3)
In [10]:
result = M + a
print( result )
print(result.shape)
[[1. 2. 3.]
 [1. 2. 3.]]
(2, 3)

In [11]:
# shape (3,2) + shape(3,) addition
M = np.ones((3, 2))
a = np.arange(3)

print(a.shape)
(3,)
In [12]:
print(a[:, np.newaxis].shape)
result = M + a[:, np.newaxis]
print(result)
(3, 1)
[[1. 1.]
 [2. 2.]
 [3. 3.]]

Universal Functions¶

  • Functions that support broadcasting are called as universal functions.
  • There are currently more than 60 universal functions.