## Show code cell source

```
import numpy as np
```

# Array algebra#

‘numpy’ makes matrix algebra **very** easy (minimal code) and **fast**. Consider two vectors, \(x\) and \(y\) and we wish to subtract \(y\) from \(x\).

`numpy`

code for this type of mathematical operation is extremely simple and readable.

```
x = np.array([10, 20, 30, 40])
y = np.array([10, 10, 10, 10])
z = x - y
print(z)
```

```
[ 0 10 20 30]
```

```
x = np.array([10, 20, 30, 40], dtype=np.int64)
y = x + 5
z = y ** 2
print(z)
```

```
[ 225 625 1225 2025]
```

## Broadcasting#

We have already seen that `numpy`

can elegantly handle an element wise addition using the following syntax:

```
x = np.array([10, 20, 30, 40])
y = x + 5
```

`numpy`

achieves this via a technique called **broadcasting**. In effect `numpy`

stretched the scalar value `5`

into an array with dimensions compatable with `x`

:

```
x = np.array([10, 20, 30, 40])
y = x + np.array([5, 5, 5, 5])
```

```
x = np.array([10, 20, 30, 40])
y = x + np.array([5, 5, 5, 5])
y
```

```
array([15, 25, 35, 45])
```

Broadcasting works for different sized arrays a well as scalars. The `numpy`

docs specifies the following broad casting rule:

“*In order to broadcast, the size of the trailing axes for both arrays in an operation must either be the same size or one of them must be one.*”

We have already seen an example where the trailing axes is one above. Here’s a more complex example:

```
a = np.array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
b = np.array([1, 2, 3])
a + b
```

```
array([[ 1, 3, 5],
[ 4, 6, 8],
[ 7, 9, 11],
[10, 12, 14]])
```

This is equivalent to the following matrix addition where b is **stretched**

```
a = np.array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
b = np.array([[ 1, 2, 3],
[ 1, 2, 3],
[ 1, 2, 3],
[ 1, 2, 3]])
a + b
```

```
array([[ 1, 3, 5],
[ 4, 6, 8],
[ 7, 9, 11],
[10, 12, 14]])
```

Note that we were able to broadcast in this instance because of the dimensions of the arrays

```
a = np.array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
b = np.array([1, 2, 3])
print(a.shape)
print(b.shape)
```

```
(4, 3)
(3,)
```

We can break `numpy`

broadcasting rules if, for example, `b`

were a lost a column.

```
a = np.array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
b = np.array([1, 2])
print(a.shape)
print(b.shape)
a + b
```

```
(4, 3)
(2,)
```

```
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-20-bc2a4615e61a> in <module>
9 print(b.shape)
10
---> 11 a + b
ValueError: operands could not be broadcast together with shapes (4,3) (2,)
```