Working with an np.ndarray#

These exercises and drills aim to build your experience of using an np.ndarry as opposed to a standard python list. Try to work through them all without looking at the answers first.

Tip: If I am stuck with how to implement a model or algorithm efficiently in `numpy` it often helps to implement it first in standard python. I can then at least check my `numpy` code is reproducing the standard python results and it is more efficient.

In practice you will come across complex problems that will make you scratch you head! If you are struggling with arrays then small steps will help!


Remember for any code where you wish to use numpy you need to import it:

import numpy as np

Exercise 1#

Task:

  • Create two numpy arrays of size 10;

  • The first array should be called array_1 have all zero integer values;

  • The second array array_2 should be a sequence of integers from 90 to 99;

  • Print the arrays.

The expected output of your code is:

[0 0 0 0 0 0 0 0 0 0]

[90 91 92 93 94 95 96 97 98 99]

# your code here ...
# example solution
array_1 = np.zeros(10, dtype=np.uint32)
array_2 = np.arange(90, 100, dtype=np.uint32)

print(array_1)
print(array_2)
[0 0 0 0 0 0 0 0 0 0]
[90 91 92 93 94 95 96 97 98 99]

Exercise 2#

Task:

  • Continue to use array_1 and array_2 from exercise 1.

  • Create a slice of array_1 to access the last 5 elements of the array;

  • Add the value 10 to each of the elements in the slice.

  • Now multiply the two arrays together and print out the result;

The expected result is:

[0, 0, 0, 0, 0, 950, 960, 970, 980, 990]
array_1 = np.zeros(10, dtype=np.uint32)
array_2 = np.arange(90, 100, dtype=np.uint32)

# slice array and add 10
array_1[5:10] += 10

array_3 = array_1 * array_2

print(array_3)
[  0   0   0   0   0 950 960 970 980 990]

Exercise 3#

You are given the following system of equations

\[x + y + z = 6\]
\[2y + 5z = −4\]
\[2x + 5y − z = 27\]

The matrix form of these equations is:

\[\begin{split} \begin{bmatrix} 1 & 1 & 1\\ 0 & 2 & 5 \\ 2 & 5 & -1 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \end{bmatrix}= \begin{bmatrix} 6\\ -4\\ 27 \end{bmatrix}\end{split}\]

Task:

  • If we denote the two matricies containing numeric data as

\[\begin{split}A = \begin{bmatrix} 1 & 1 & 1\\ 0 & 2 & 5 \\ 2 & 5 & -1 \end{bmatrix}\end{split}\]
\[\begin{split}B = \begin{bmatrix} 6\\ -4\\ 27 \end{bmatrix}\end{split}\]
  • Represent \(A\) and \(B\) as seperate arrays.

  • Print the arrays to the screen.

  • Print the shape of the arrays.

# your code here...
# example solution
a = np.array([[1, 1, 1], [0, 2, 5], [2, 5, -1]])
b = np.array([6, -4, 27])

print(a, a.shape)
print(b, b.shape)
[[ 1  1  1]
 [ 0  2  5]
 [ 2  5 -1]] (3, 3)
[ 6 -4 27] (3,)

Exercise 4#

To solve for the unknowns \(x\), \(y\) and \(z\) we need to take the dot product of the inverse of \(A\) and \(B\)

\[\begin{split}\begin{bmatrix} x \\ y \\ z \end{bmatrix} = \begin{bmatrix} 1 & 1 & 1\\ 0 & 2 & 5 \\ 2 & 5 & -1 \end{bmatrix}^{-1} \begin{bmatrix} 6\\ -4\\ 27 \end{bmatrix}\end{split}\]

There are number of ways we can solve this in numpy. One option is to use the np.dot function to take the dot product. This can be combined with np.linalg.inv to take the inverse of a matrix. Or more generally we can call np.linalg.solve() to solve a system of linear equations.

Task

  • Using the matricies constructed in exercise 3 and the functions described above, solve for \(x\), \(y\) and \(z\)

# your code here
# example solution 1
np.dot(np.linalg.inv(a), b)
array([ 5.,  3., -2.])
# example solution 2
np.linalg.solve(a, b)
array([ 5.,  3., -2.])

Exercise 5#

The code below generates a 1D array vector with shape (15,). It is a sequence of numbers from 0 to 14.

Task:

  • Reshape the 1d array into a 2d array with shape (5, 3)

The expected result is

[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]
 [12 13 14]]
vector = np.arange(15)
vector.shape

# your code here ...
(15,)
# example solution
matrix_2d = np.arange(15).reshape(-1,3)
print(matrix_2d.shape)
print(matrix_2d)
(5, 3)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]
 [12 13 14]]

Exercise 6#

  • Use the 2 dimensional matrix that is the answer to exercise 5;

  • Slice the array to return elements 1 to 3 of the first column.

The expected output is:

[3 6 9]
# your code here ...
# example answer
first_column_slice = matrix_2d[1:4,0]
print(f'First column: {first_column_slice}')
First column: [3 6 9]

Exercise 7#

The code below generates a 1D array vector with shape (100,). It is a sequence of numbers from 0 to 99.

Task:

  • Reshape the 1d array into a 3d array with shape (2, 10, 5)

When printed to the screen the expected array should take the form

[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]
  [15 16 17 18 19]
  [20 21 22 23 24]
  [25 26 27 28 29]
  [30 31 32 33 34]
  [35 36 37 38 39]
  [40 41 42 43 44]
  [45 46 47 48 49]]

 [[50 51 52 53 54]
  [55 56 57 58 59]
  [60 61 62 63 64]
  [65 66 67 68 69]
  [70 71 72 73 74]
  [75 76 77 78 79]
  [80 81 82 83 84]
  [85 86 87 88 89]
  [90 91 92 93 94]
  [95 96 97 98 99]]]
vector = np.arange(100)
print(vector.shape)

# your code here ...
(100,)
# example answer ...
vector = np.arange(100)
matrix_3d = vector.reshape(-1, 10, 5)
print(matrix_3d.shape)
print(matrix_3d)
(2, 10, 5)
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]
  [15 16 17 18 19]
  [20 21 22 23 24]
  [25 26 27 28 29]
  [30 31 32 33 34]
  [35 36 37 38 39]
  [40 41 42 43 44]
  [45 46 47 48 49]]

 [[50 51 52 53 54]
  [55 56 57 58 59]
  [60 61 62 63 64]
  [65 66 67 68 69]
  [70 71 72 73 74]
  [75 76 77 78 79]
  [80 81 82 83 84]
  [85 86 87 88 89]
  [90 91 92 93 94]
  [95 96 97 98 99]]]

Exercise 8#

Remember one way to get to grips with slicing a 3D array is to look at the shape and think about how it all links together. In the last exercise the array td has a shape \((2, 10, 5)\). I think of this as 2 rows, each of which contains 10 sub vectors of length 5

Using the 3 dimensional array constructed in exercise 7 take the following slices and if necessary make the updates to the original data:

  • The second (i.e. index = 1) sub vector of each matrix. The expected answer is:

[[ 5  6  7  8  9]
 [55 56 57 58 59]]
  • Elements 1 to 3 of the fifth subvector in each matrix. The expected answer is:

[[21 22 23]
 [71 72 73]]
  • Can you produce following array from the original?

[[   2    7   12 9999   22   27   32   37   42   47]
 [   3    8   13 9999   23   28   33   38   43   48]
 [   4    9   14 9999   24   29   34   39   44   49]]

Hints for final task:

  • You are replacing the values 17, 18 and 19.

  • From the first row of the array select the third sub vector.

  • In this subvector set the final 3 columns to 9999

  • Transpose the array.

  • To transpose an array you can call .T from an array. E.g.

>>> matrix = np.arange(10).reshape(-1, 5)
>>> print(matrix)

[[0 1 2 3 4]
 [5 6 7 8 9]]

>>> print(matrix.T)

[[0 5]
 [1 6]
 [2 7]
 [3 8]
 [4 9]]
# your code here ...
# Example solutions

# The first sub vector of each matrix.
vector = np.arange(100)
matrix_3d = vector.reshape(-1, 10, 5)
print(matrix_3d[:, 1, :])
[[ 5  6  7  8  9]
 [55 56 57 58 59]]
# Elements 1 to 3 of the fifth subvector in each matrix.
vector = np.arange(100)
matrix_3d = vector.reshape(-1, 10, 5)
print(matrix_3d[:, 4, 1:4])
[[21 22 23]
 [71 72 73]]
# final task
vector = np.arange(100)
matrix_3d = vector.reshape(-1, 10, 5)

to get the first row we can do this:

matrix_3d[0]
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24],
       [25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34],
       [35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44],
       [45, 46, 47, 48, 49]])

to get the sub vector at index 3 we use an additional argument in the slicing.

matrix_3d[0, 3]
array([15, 16, 17, 18, 19])

we can use standard slicing notation for the third dimension. I.e for the final 3 values in an array of length 5 we could use

matrix_3d[0, 3, 2:]
array([17, 18, 19])

or alternatively

matrix_3d[0, 3, -3:]
array([17, 18, 19])

This is just a view of the original array in memory. So to update the original array we use:

# remember that slicing is a view of the original data.
matrix_3d[0, 3, 2:] = 9999

# slice and transpose
column_slice = matrix_3d[0, :, 2:].T

print(column_slice)
[[   2    7   12 9999   22   27   32   37   42   47]
 [   3    8   13 9999   23   28   33   38   43   48]
 [   4    9   14 9999   24   29   34   39   44   49]]