3.3. Array Broadcasting¶
3.3.2. Broadcasting Rules¶
Source [NumpyCL19a]
Operations between multiple array objects are first checked for proper shape match
Mathematical operators (
+
,-
,*
,/
,exp
,log
, ...) apply element by element, on valuesReduction operations (
mean
,std
,skew
,kurt
,sum
,prod
, ...) apply to whole array, unless an axis is specifiedMissing values propagate, unless explicitly ignored (
nanmean
,nansum
, ...)
3.3.3. Addition¶
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[4, 5, 6], [7, 8, 9]])
c = np.array([1, 2, 3])
d = np.array([4, 5])
a + a
# array([[ 2, 4, 6],
# [ 8, 10, 12]])
a + b
# array([[ 5, 7, 9],
# [11, 13, 15]])
a + c
# array([[2, 4, 6],
# [5, 7, 9]])
a + d
# Traceback (most recent call last):
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
3.3.4. Subtraction¶
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[4, 5, 6], [7, 8, 9]])
c = np.array([1, 2, 3])
d = np.array([4, 5])
a - a
# array([[0, 0, 0],
# [0, 0, 0]])
a - b
# array([[-3, -3, -3],
# [-3, -3, -3]])
a - c
# array([[0, 0, 0],
# [3, 3, 3]])
a - d
# Traceback (most recent call last):
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
3.3.5. Division¶
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[4, 5, 6], [7, 8, 9]])
c = np.array([1, 2, 3])
d = np.array([4, 5])
a / a
# array([[1., 1., 1.],
# [1., 1., 1.]])
a / b
# array([[0.25 , 0.4 , 0.5 ],
# [0.57142857, 0.625 , 0.66666667]])
a / c
# array([[1. , 1. , 1. ],
# [4. , 2.5, 2. ]])
a / d
# Traceback (most recent call last):
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
3.3.6. True Division¶
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[4, 5, 6], [7, 8, 9]])
c = np.array([1, 2, 3])
d = np.array([4, 5])
a // a
# array([[1, 1, 1],
# [1, 1, 1]])
a // b
# array([[0, 0, 0],
# [0, 0, 0]])
a // c
# array([[1, 1, 1],
# [4, 2, 2]])
a // d
# Traceback (most recent call last):
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
3.3.7. Modulo¶
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[4, 5, 6], [7, 8, 9]])
c = np.array([1, 2, 3])
d = np.array([4, 5])
a % a
# array([[0, 0, 0],
# [0, 0, 0]])
a % b
# array([[1, 2, 3],
# [4, 5, 6]])
a % c
# array([[0, 0, 0],
# [0, 1, 0]])
a % d
# Traceback (most recent call last):
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
3.3.8. Power¶
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[4, 5, 6], [7, 8, 9]])
c = np.array([1, 2, 3])
d = np.array([4, 5])
a ** a
# array([[ 1, 4, 27],
# [ 256, 3125, 46656]])
a ** b
# array([[ 1, 32, 729],
# [ 16384, 390625, 10077696]])
a ** c
# array([[ 1, 4, 27],
# [ 4, 25, 216]])
a ** d
# Traceback (most recent call last):
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
3.3.9. Root¶
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[4, 5, 6], [7, 8, 9]])
c = np.array([1, 2, 3])
d = np.array([4, 5])
a ** (1/a)
# array([[1. , 1.41421356, 1.44224957],
# [1.41421356, 1.37972966, 1.34800615]])
a ** (1/b)
# array([[1. , 1.14869835, 1.20093696],
# [1.21901365, 1.22284454, 1.22028494]])
a ** (1/c)
# array([[1. , 1.41421356, 1.44224957],
# [4. , 2.23606798, 1.81712059]])
a ** (1/d)
# Traceback (most recent call last):
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
3.3.10. Array Multiplication¶
Multiplication
*
remains elementwise and does not correspond to matrix multiplication.
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[4, 5, 6], [7, 8, 9]])
c = np.array([1, 2, 3])
d = np.array([4, 5])
a * a
# array([[ 1, 4, 9],
# [16, 25, 36]])
a * b
# array([[ 4, 10, 18],
# [28, 40, 54]])
a * c
# array([[ 1, 4, 9],
# [ 4, 10, 18]])
a * d
# Traceback (most recent call last):
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
3.3.11. Matrix Multiplication¶


import numpy as np
a = np.array([[1, 2, 3],
[4, 5, 6]])
b = np.array([[1, 2],
[3, 4],
[5, 6]])
a @ b
# array([[22, 28],
# [49, 64]])
import numpy as np
a = np.array([[1, 2, 3],
[4, 5, 6]])
b = np.array([[4, 5, 6],
[7, 8, 9]])
a @ b
# Traceback (most recent call last):
# ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 3)
3.3.12. Dot¶
np.dot()
If either a or b is 0-D (scalar), it is equivalent to
multiply
and usingnumpy.multiply(a, b)
ora * b
is preferred.If both a and b are 1-D arrays, it is inner product of vectors (without complex conjugation).
If both a and b are 2-D arrays, it is matrix multiplication, but using
matmul
ora @ b
is preferred.If a is an N-D array and b is a 1-D array, it is a sum product over the last axis of a and b.
If a is an N-D array and b is an M-D array (where
M>=2
), it is a sum product over the last axis of a and the second-to-last axis of b:dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])
import numpy as np
a = np.array([1, 2, 3], float)
b = np.array([0, 1, 1], float)
np.dot(a, b)
# 5.0
import numpy as np
a = np.array([[0, 1], [2, 3]], float)
b = np.array([2, 3], float)
c = np.array([[1, 1], [4, 0]], float)
np.dot(b, a)
# array([ 6., 11.])
np.dot(a, b)
# array([ 3., 13.])
np.dot(a, c)
# array([[ 4., 0.],
# [ 14., 2.]])
np.dot(c, a)
# array([[ 2., 4.],
# [ 0., 4.]])
3.3.13. Assignments¶
"""
* Assignment: Numpy Broadcasting Arithmetic
* Complexity: easy
* Lines of code: 4 lines
* Time: 3 min
English:
1. Use data from "Given" section (see below)
2. For given: `a: np.ndarray`, `b: np.ndarray`, `c: np.ndarray`
3. Calculate square root of each element in `a` and `b`
4. Calculate second power (square) of each element in `c`
5. Add elements from `a` to `b`
6. Multiply the result by `c`
7. Compare result with "Tests" section (see below)
Polish:
1. Użyj danych z sekcji "Given" (patrz poniżej)
2. Dla danych: `a: np.ndarray`, `b: np.ndarray`, `c: np.ndarray`
3. Oblicz pierwiastek kwadratowy każdego z elementu w `a` i `b`
4. Oblicz drugą potęgę (kwadrat) każdego z elementu w `c`
5. Dodaj elementy z `a` do `b`
6. Przemnóż wynik przez `c`
7. Porównaj wyniki z sekcją "Tests" (patrz poniżej)
Tests:
>>> type(result)
<class 'numpy.ndarray'>
>>> result
array([[ 1.41421356, 2.73205081],
[45.254834 , 0. ]])
"""
# Given
import numpy as np
a = np.array([[0, 1], [2, 3]], float)
b = np.array([2, 3], float)
c = np.array([[1, 1], [4, 0]], float)
result = ...
"""
* Assignment: Numpy Broadcasting Type Cast
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min
English:
1. For given: `a: np.ndarray`, `b: np.ndarray` (see below)
2. Add `a` and `b`
3. Add `b` and `a`
4. What happened?
Polish:
1. Dla danych: `a: np.ndarray`, `b: np.ndarray` (patrz sekcja input)
2. Dodaj `a` i `b`
3. Dodaj `b` i `a`
4. Co się stało?
Tests:
>>> type(ab)
<class 'numpy.ndarray'>
>>> type(ba)
<class 'numpy.ndarray'>
>>> ab
array([[5, 1],
[2, 3]])
>>> ba
array([[5, 1],
[2, 3]])
"""
# Given
import numpy as np
a = np.array([[1, 0], [0, 1]])
b = [[4, 1], [2, 2]]
"""
* Assignment: Numpy Broadcasting Matmul
* Complexity: easy
* Lines of code: 4 lines
* Time: 3 min
English:
1. For given: `a: np.ndarray`, `b: np.ndarray` (see below)
2. Multiply `a` and `b` using scalar multiplication
3. Multiply `a` and `b` using matrix multiplication
4. Multiply `b` and `a` using scalar multiplication
5. Multiply `b` and `a` using matrix multiplication
6. Discuss results
Polish:
1. Dla danych: `a: np.ndarray`, `b: np.ndarray` (patrz sekcja input)
2. Przemnóż `a` i `b` używając mnożenia skalarnego
3. Przemnóż `a` i `b` używając mnożenia macierzowego
4. Przemnóż `b` i `a` używając mnożenia skalarnego
5. Przemnóż `b` i `a` używając mnożenia macierzowego
6. Omów wyniki
Tests:
>>> mul_ab(a, b) # doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
ValueError: operands could not be broadcast together with shapes (4,4) (4,2)
>>> matmul_ab(a, b)
array([[ 9, 2],
[ 7, 3],
[21, 8],
[28, 8]])
>>> mul_ba(b, a) # doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
ValueError: operands could not be broadcast together with shapes (4,2) (4,4)
>>> matmul_ba(b, a)
Traceback (most recent call last):
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 4 is different from 2)
"""
# Given
import numpy as np
a = np.array([[1, 0, 1, 0],
[0, 1, 1, 0],
[3, 2, 1, 0],
[4, 1, 2, 0]])
b = np.array([
[4, 1],
[2, 2],
[5, 1],
[2, 3]])
def mul_ab(a, b):
return ...
def matmul_ab(a, b):
return ...
def mul_ba(b, a):
return ...
def matmul_ba(b, a):
return ...