# NumPy: Operations

April 24, 2019

In the last tutorial, we learnt about NumPy arrays, indexing and slicing.

In this tutorial, we will be learning about the various mathematical operations and functions NumPy supports.

You are encouraged to **follow along** with the tutorial and play around with NumPy, tinkering with the code and making sure you’re getting the hang of it. Let’s get started!

# Set-up

Let’s start by defining some arrays

```
import numpy as np
# Create a 1-dimensional array
a = np.array([1,4,2,3,5,7,8,6])
print('array "a"')
print(a)
print()
# Create a 2-dimensional array
b = np.array([[1,0,1,0,2,3], [1,3,0,1,2,0], [0,1,0,0,1,3]])
print('array "b"')
print(b)
```

# Element-wise operations (add, multiply, etc)

We can conduct mathematical calculations on NumPy arrays. Some of the standard mathematical formulas (additional, subtraction, multiplication, division, etc) are shown below.

Let’s start by defining an array `c`

to be `b + 5`

:

```
c = b + 5
print(c)
```

As you can see, adding a scalar to a NumPy array adds that value to every element of the array.

Subtraction, multiplication, division, etc work the same way. Try editing the code above and try out some of these operations.

Now, let’s try some operations between two NumPy arrays. We can directly use arithmetic operators (like `+`

), or we can use equivalent NumPy functions (such as `add()`

).

Element-wise addition:

```
# Element-wise addition
print('Element-wise sum of "b" and "c"')
print(b + c)
print()
print('Element-wise sum of "b" and "c"')
print(np.add(b, c))
```

Element-wise subtraction:

```
# Element-wise subtraction
print('Element-wise difference of "b" and "c"')
print(b - c)
print()
print('Element-wise difference of "b" and "c"')
print(np.subtract(b, c))
```

Element-wise multiplication:

```
# Element-wise multiplication
print('Element-wise multiplication of "b" and "c"')
print(b * c)
print()
print('Element-wise multiplication of "b" and "c"')
print(np.multiply(b, c))
```

Element-wise division:

```
# Element-wise division
print('Element-wise division of "b" and "c" ')
print(b / c)
```

Note:The arrays are implicitly converted to`float`

in latest NumPy versions.

NumPy also includes a number of element-wise operations, such as `sqrt`

(square-root) and `log`

(logarithm).

```
# Element-wise square-root
print('Element-wise square root of array "b"')
print(np.sqrt(b))
```

# Aggregation operations (sum, min, max, etc)

Apart from element-wise operations, NumPy also includes a host of aggregation operations like `sum`

, `min`

, `max`

, `mean`

, etc.

All of these functions are available directly as functions in the NumPy library, as in `np.sum(b)`

, `np.min(b)`

, etc. And most of the functions are also available as methods of the array class. Hence, we can also do `b.sum()`

, `b.min()`

, etc.

Lastly, aggregation operations can work over all elements of the array, or over specific dimensions. For example, we can use `axis=0`

to perform an operation for each column.

Some example will help:

```
# Sum of all elements
print('Sum of all elements of array "b"')
print(b.sum())
print()
# Sum of each column
print('Sum of each column of array "b"')
print(b.sum(axis=0))
print()
# Sum of each row
print('Sum of each row of array "b"')
print(b.sum(axis=1))
```

Similarly, we have functions like `min`

(minimum), `max`

(maximum), `cumsum`

(cumulative summation).

```
# Minimum of all values
print('Minimum of all values of array "b"')
print(b.min())
print()
# Maximum across axis 1
print('Maximum across axis 1 of array "b"')
print(b.max(axis=1))
print()
# Cumulative sum across axis 0
print('Cumulative sum across axis 0 of array "b"')
print(b.cumsum(axis=0))
```

And also `mean`

, `median`

, `std`

(standard deviation).

```
print('Mean along axis 0 of array "b"')
print(b.mean(axis=0))
print()
print('Median along axis 0 of array "b"')
print(np.median(b, axis=1))
print()
print('Standard deviation along axis 0 of array "b"')
print(np.std(b, axis=0))
print()
print('Mean along axis 0 of array "b"')
print(np.mean(b, axis=0))
```

We can also find all the unique elements in an array.

```
print('unique elements in array "b"')
print(np.unique(b))
```

# Matrix Operations (dot products, matrix multiplication, etc)

Now, let’s look at some matrix operations that NumPy supports. `np.dot(x, y)`

can be used to perform both dot-products as well as matrix multiplication. Let’s see how.

First, we’ll create two more arrays, `v`

and `w`

.

```
# Create array "v"
v = b[:, 0]
print('array "v"')
print(v)
print()
# Create array "w"
w = b[:, 1]
print('array "w"')
print(w)
```

Dot product:

```
# Inner product of vectors: v[0]*w[0] + v[1]*w[1] + ... v[n]*w[n]
print('Dot product of "v" and "w"')
print(v.dot(w)) # or np.dot(v, w)
print()
print('Dot product of "v" and "v"')
print(v.dot(v)) # or np.dot(v, v)
```

When the arrays are 2-dimensional, dot-product is equivalent to performing matrix multiplication. Below are examples of matrix-vector multiplication and matrix-matrix multiplication.

```
# Transpose of a matrix
print('Transpose of "b"')
print(b.T)
print()
# Matrix-vector product
print('Matrix-vector product of "b-transpose" and "v"')
print(np.dot(b.T, v))
print()
# Matrix-matrix product (matrix multiplication)
print('Matrix-matrix product of "b-transpose" and "b"')
print(np.dot(b.T, b))
```

For dot products and matrix multiplication to be performed, the dimensions of the arrays need to be compatible. If they are not, NumPy will raise an exception.

```
# Incompatible dimensions (matrix-vector)
print(np.dot(b, v))
```

```
# Incompatible dimensions (matrix-matrix)
print(np.dot(b, c))
```

# Sorting

To sort a NumPy array, we can use the `sort()`

function.

This function returns a sorted array. The original array is not modified.

```
print('array "a"')
print(a)
print()
# sort array "a"
print('sorted array "a"')
print(np.sort(a))
```

The `sort()`

function also accepts an `axis`

parameter.

`axis`

parameter is used to specify the axis along which we want to sort. In NumPy, axis values increase from the outside-in. For example, if we pass a 2D array and axis is 0, NumPy will sort each column. If axis is 1, NumPy will sort each row.

`axis = -1`

sorts along the last axis. This is also the default value. `axis`

can also be `None`

, in which case, the array is flattened and then the elements are sorted.

Let’s look at some examples:

```
print('array "b"')
print(b)
print()
# sort array "b" along rows, axis 1
print('array "b" sorted along rows (axis=1)')
print(np.sort(b, axis=1))
print()
# sort array "b" along rows (also the last axis in this case)
print('array "b" sorted along rows (axis=-1)')
print(np.sort(b, axis=-1))
print()
# sort array "b" along columns, axis 0
print('array "b" sorted along columns (axis=0)')
print(np.sort(b, axis=0))
print()
# sort array "b" after flattening it
print('array "b" flattened and then sorted (axis=None)')
print(np.sort(b, axis=None))
```

If there are any `nan`

values in the array, they are always placed at the end of the sorted array. Let’s see an example:

```
# create a new array with 'nan' values
z = np.array([0, np.nan, 1, 2, np.nan, 7, 3, 5, 1, np.nan])
print('array with "nan" values')
print(z)
print()
# sort array and display
print('sorted array')
print(np.sort(z))
```

You can also sort an array inplace (i.e. sort the original array instead of returning a new sorted array) by using the `.sort()`

method of a NumPy array (as opposed to doing `np.sort(array)`

).

For example, to sort every column of array `b`

inplace, we do:

```
b.sort(axis=0)
print(b)
```

# Summary

In summary, in this tutorial we learnt

- perform element-wise operations like addition, subtraction, etc. and functions like square root, log, etc.
- performing aggregation operations like sum, cumulative sum, mean, etc
- performing dot products and matrix multiplications
- sorting numpy arrays

In the next tutorial, we will learn how to manipulate and modify NumPy arrays.