NumPy Array Maths and Broadcasting
NumPy lets you do maths on every item of an array at once, without writing a loop.
Element-Wise Arithmetic
When you use +, -, *, / or ** between two arrays of the same shape, NumPy works item by item:
Example
import numpy as np
morning = np.array([120, 90, 150])
evening = np.array([80, 110, 60])
print(morning + evening)
print(morning - evening)
print(morning * 2)
print(morning / 10)
print(evening ** 2)[200 200 210] [ 40 -20 90] [240 180 300] [12. 9. 15.] [ 6400 12100 3600]
This style is called vectorised code. It is short, clear and fast.
Universal Functions (ufuncs)
NumPy has many functions that work on every element. They are called universal functions or ufuncs.
Example
import numpy as np
arr = np.array([1, 4, 9, 16])
print(np.sqrt(arr))
print(np.square(arr))
print(np.log10(np.array([10, 100, 1000])))
print(np.round(np.array([2.456, 7.891]), 1))
print(np.abs(np.array([-5, 3, -2])))[1. 2. 3. 4.] [ 1 16 81 256] [1. 2. 3.] [2.5 7.9] [5 3 2]
| Function | What it does |
|---|---|
np.sqrt() | Square root |
np.square() | Square |
np.exp(), np.log() | e to the power, natural log |
np.round(a, n) | Round to n decimals |
np.abs() | Absolute value |
np.sin(), np.cos() | Trigonometry (radians) |
np.add(), np.multiply() | Same as + and * |
Broadcasting
Broadcasting lets NumPy work with arrays of different shapes. The smaller one is "stretched" to match the bigger one, without really copying data.
The simplest case is an array and a single number:
Example
import numpy as np
prices = np.array([500, 1200, 800])
print(prices + 100) # the 100 is added to every item[ 600 1300 900]
It also works between a 2-D array and a 1-D row. Here, each column gets its own bonus:
Example
import numpy as np
# rows = students, columns = Maths, English, Science
marks = np.array([
[70, 65, 80],
[55, 72, 60]
])
bonus = np.array([5, 0, 10])
print(marks + bonus)[[75 65 90] [60 72 70]]
The Broadcasting Rule
NumPy compares the shapes from the right side. Two dimensions fit if they are equal, or if one of them is 1. If they do not fit, you get an error:
Example
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]]) # shape (2, 3)
b = np.array([10, 20]) # shape (2,)
print(a + b)ValueError: operands could not be broadcast together with shapes (2,3) (2,)
To add a value per row instead, make it a column with shape (2, 1): b.reshape(2, 1). Then the shapes (2, 3) and (2, 1) fit.
Comparisons
Comparison operators also work item by item, and give an array of booleans:
Example
import numpy as np
marks = np.array([45, 78, 52, 30, 90])
print(marks >= 50)[False True True False True]
You will use these boolean arrays to filter data in a later lesson.
Matrix Multiplication
* multiplies item by item. For real matrix multiplication (rows times columns), use @ or np.dot():
Example
import numpy as np
qty = np.array([[2, 1], [0, 3]]) # orders of two shops
price = np.array([[100], [250]]) # price of each item
print(qty @ price)[[450] [750]]
Shop one spends 2 x 100 + 1 x 250 = 450, and shop two spends 0 x 100 + 3 x 250 = 750.
Exercise
Exercise
What does np.array([1, 2, 3]) + np.array([10, 20, 30]) return?
