Like a standard Python list, a NumPy array
can be accessed using the normal indexing syntax. This includes the negative indexing in order to count from the end of the array:
import numpy as np
a = np.arange(10)
a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
a[0], a[2], a[-1]
(0, 2, 9)
For a multidimensional array, the index is a tuple of integers. Unlke a normal Python list
it is possible to put more than one number in the square brackets rather than having to chain up multiple pairs of square brackets:
a = np.arange(9).reshape((3,3))
a
array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
a[1, 1]
4
a[2, 1] = 10
a
array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 10, 8]])
In 2D, the first dimension corresponds to rows, the second to columns.
For a multidimensional array, you can under-specify the indices so a[1]
is interpreted by taking all elements in the unspecified dimensions. In this case all the columns of row number 1
.
a[1]
array([3, 4, 5])
If you want to get a specific column, you can use ...
as a placeholder like so:
a[..., 2]
array([2, 5, 8])
Like a normal Python list, a NumPy array can also be sliced:
a = np.arange(10)
a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
a[2:6] # index 2 to (but not including) 6
array([2, 3, 4, 5])
a[3:-2] # index 4 to (but not including) the second-last entry
array([3, 4, 5, 6, 7])
a[2:9:3] # 2 to 9 in steps of 3
array([2, 5, 8])
Note that not all entries are required, the first defaults to 0
, the second to '1 past the end' and the third to 1
:
a[4:] # index 4 to end of array
array([4, 5, 6, 7, 8, 9])
a[::2] # even-index entries
array([0, 2, 4, 6, 8])
It is also possible to combine slicing with a multi-dimensional array:
a = np.arange(36).reshape((6,6))
a
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]])
a[0, 3:5]
array([3, 4])
a[4:, 4:]
array([[28, 29], [34, 35]])
a[:, 2]
array([ 2, 8, 14, 20, 26, 32])
a[2::2, ::2]
array([[12, 14, 16], [24, 26, 28]])
You can also combine assignment and slicing:
a = np.arange(10)
a[5:] = 10
a
array([ 0, 1, 2, 3, 4, 10, 10, 10, 10, 10])
b = np.arange(5)
a[5:] = b[::-1]
a
array([0, 1, 2, 3, 4, 4, 3, 2, 1, 0])
Try the different flavours of slicing, using start
, end
and step
: starting from a linspace()
, try to obtain odd numbers counting backwards, and even numbers counting forwards.
Create the following arrays with correct data types (don't just paste them verbatim into a np.array()
call):
[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 2],
[1, 6, 1, 1]]
[[0., 0., 0., 0., 0.],
[2., 0., 0., 0., 0.],
[0., 3., 0., 0., 0.],
[0., 0., 4., 0., 0.],
[0., 0., 0., 5., 0.],
[0., 0., 0., 0., 6.]]
Par on course: 3 statements for each
Hint: Individual array elements can be accessed similarly to a list
, e.g. [1]
or a[1, 2]
.
Hint: Examine the docstring for diag()
.
Skim through the documentation for np.tile()
, and use this function to construct the array:
[[4, 3, 4, 3, 4, 3],
[2, 1, 2, 1, 2, 1],
[4, 3, 4, 3, 4, 3],
[2, 1, 2, 1, 2, 1]]
NumPy arrays can be indexed with slices, but also with boolean or integer arrays (masks). This method is called fancy indexing. It creates copies not views.
Using a boolean mask:
np.random.seed(3)
a = np.random.randint(0, 20, 15)
a
array([10, 3, 8, 0, 19, 10, 11, 9, 10, 6, 0, 12, 7, 14, 17])
(a % 3 == 0) # an array with True where the condition "a[i] % 3 == 0" is true.
array([False, True, False, True, False, False, False, True, False, True, True, True, False, False, False])
mask = (a % 3 == 0)
multiples_of_three = a[mask] # or, a[a%3==0]
multiples_of_three # extract a sub-array with the mask
array([ 3, 0, 9, 6, 0, 12])
Indexing with a mask can be very useful to assign a new value to a sub-array:
a[a % 3 == 0] = -1
a
array([10, -1, 8, -1, 19, 10, 11, -1, 10, -1, -1, -1, 7, 14, 17])
You can also do fancy indexing with an array of integers, where the same index is repeated several times:
a = np.arange(0, 100, 10)
a
array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
a[[2, 3, 2, 4, 2]]
array([20, 30, 20, 40, 20])
New values can be assigned with this sort of indexing:
a[[9, 7]] = -100
a
array([ 0, 10, 20, 30, 40, 50, 60, -100, 80, -100])
Try using fancy indexing on the left and array creation on the right to assign values into an array, for instance by setting parts of a large 2D array to zero.
Continue to the [next section](numerical operations.ipynb).