For those I didn’t know the answer to, I used a combination of Google and The NumPy API Reference to try to work out the solution, so yes,
you should research these if you want to practice! The exercises selected here cover many of the features of NumPy, but it’s not meant to be exhaustive.
For example, the linear algebra features in numpy.linalg package are not covered.
In the exercises that follow, any unqualified references to an “array” mean a NumPy array, not a native Python array.
References to “np” refer to the NumPy package in the usual way it is aliased: “import numpy as np“. ^{1}
NumPy has several functions that will return an nDimensional array. These exercises ask you to recall these functions to create simple (1dimensional) arrays.
 Using a NumPy function, how would you create a one dimensional NumPy array of the numbers from 10 to 100, counting by 10?
 How could you do create the same NumPy array using a Python range and a list?
 What happens if you pass no arguments to the
np.array()
?
 How might you create a NumPy array of the capital letters, AZ?
 How would you create a tenelement array of all zeros?
 What would the data type of such an array be?
 How would you find the data type given in #6.
 What function would return the same number of elements, but of all ones?
 How could you create a ten element array of random integers between 1 and 5 (inclusive)?
 How can you create a normal distribution of 10 numbers, centered on 5?
 What code would create an array of 10 random numbers between zero and one?
Creating and Using Multidimensional arrays
In this section, we move past onedimensional arrays. As a reminder, many of the same functions that we used to create onedimensional arrays select either a single scalar value for the number of elements to create or a tuple representing the shape of the array in higher dimensions.
 Consider the code:
np.ones((3,5))
and np.zeros((3,5)))
. Does this A) create an array of three arrays containing five elements each or B) create an array of five arrays containing three elements each?
 Consider an array named
myarray
that is displayed as in the block below. What value does the code myarray[1,2]
return? A) 10 B) 7.
1
2
3
4
5

# myarray:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])

 Given myarray as shown above, what is the value of myarray.ndim?
 An array of three arrays of four elements each like this has twelve elements, of course. How could you create a new array consisting of two arrays of six elements each?
 Given myarray from #13, and the code
x = myarray
, what would x[0,0] == 42
do?
 How could you create a twodimensional, 3 x 4 array (three arrays of four elements each) with random numbers from 1 to 10?
 How could you create an array of the same size as #17, filled with zeros.
 Given this code:
1
2
3
4
5

z_list = [z for z in range(0,5)]
y_list = [z_list for y in range(0,4)]
x_list = [y_list for x in range(0,3)]
x_array = np.array(x_list)

What would x_array.shape()
return?
 Given x_array from #19, what is the value for
x_array.ndim
?
 Given an array, named “arr“, that looks like:
1
2

array([[0, 1, 2],
[3, 4, 5]])

How could you display an array that looks like:
1
2
3

array([[0, 3],
[1, 4],
[2, 5]])

Indexing and Slicing TwoDimensional Arrays
NumPy arrays support indexing and slicing across using scalars and tuples. For questions #2228, use the following array, assigned to the variable, four_by_five
. Assume that the rows are the “outer” arrays of five elements each and that the nth element within all the rows is a column:
1
2
3
4
5
6

# four_by_five:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]])

 Write an expression to return the first row. (It will be a fiveelement array).
 Write an expression to return the last row. (It will be a fiveelement array).
 What does
four_by_five[2,3]
return?
 What does
four_by_five[3,2]
return?
 How could you return the first column? It will be a (fourelement array ending with 16.)
 What does
four_by_five[:, 3:5]
return?
 Write an expression to return the last two columns of the middle two rows.
Vectorized operations are implemented in NumPy so that many mathematical and logical functions operate across the whole array. These vectorized operations act on every array element without writing a Python loop. The most common ways to do this are to combine the array with itself, with an array of the same shape, or with a scalar value.
To keep it simple, let’s use a small onedimensional array to begin. For exercises #2938, use the following definitions:
1
2
3
4
5

one_dim = np.arange(1,6)
one_dim
# Output
array([ 1, 2, 3, 4, 5])

 What would be the result of
one_dim * 2
?
 What would be returned by this expression:
one_dim + np.arange(5, 0, 1)
?
 How many zeros are in the array returned by
one_dim  one_dim
?
 What is the result of
one_dim > 2
?
 For NumPy arrays, logical operations are done with the operators “&” and ““, rather than the usual Python “and” and “or”. Given that, what would be the result of this expression?
(one_dim > 4)  (one_dim == 1)
 What is the result of this expression:
one_dim
np.absolute
take the absolute value of each element. Given that, what would the result be of the following expression: np.absolute((one_dim[3:])
 This exercise and #36 deal with sequence functions, which operate on the whole array rather than perelement. What is returned by
one_dim.sum()
?
 Break out those pictures of the unit circle for this one, for some trigonometry so simple a history major can do it! (I should know).
As background, we can round numbers to a decimal precision using
np.around(arr, num_decimals)
, and get the sine of an angle (in radians) using np.sin
. So with that, given the following:
1

arr = np.array([0., .5, 1.0, 1.5, 2.0]) * np.pi

What are the values for: np.around(np.sin(arr), 0)
 For the defined above in #36, what are the values for:
np.around(np.cos(arr), 0)
 You’re asked to save the following two arrays as is to a file,
data.npz
. The arrays should be named as they are here in the file. How could you do it?
1
2

people = np.array(["John", "Jenniffer", "Helen", "Miryam"])
languages = np.array([2, 2, 1, 1])

 Assuming you saved the file,
data.npz
, in #39, how could you reload the arrays into two new variables: people2
and languages2
?
 Given:
arr = np.arange(1,13).reshape(3,4)
; How could you save it to a CSV file, myrray.csv
.
 Given the CSV file saved in #40, how could you load it back into a variable,
arr2
?
Since you’ve been working hard on these exercises, let’s relax a little with some simple characteroriented (string) functions, from the np.char
package. These are vectorized (elementwise) versions of the Python standard library functions. Proving that every Python blog gets around to the Lumberjack Song eventually, here’s the NumPy array we’ll use for the problems in this section:
1
2
3
4
5
6

lumberjack = np.array("I'm a lumberjack and I'm OK I sleep all night and I work all day".split(" "))
lumberjack
# Output
array(["I'm", 'a', 'lumberjack', 'and', "I'm", 'OK', 'I', 'sleep', 'all',
'night', 'and', 'I', 'work', 'all', 'day'], dtype='<U10')

 What would you expect the value of
np.char.capitalize(lumberjack)[2]
to be?
 How could you surround each string with an initial and final asterisk character (*)?
 The function,
np.where
, can be used to create an array of indexes that can be used to index into the original array to subset an array based on a condition. Given that background, can you evaluate the following?
1

lumberjack[np.where(np.char.str_len(lumberjack) >=5)]

NumPy supports a variety of methods for array creation.
 How would you create a one dimensional NumPy array of the numbers from 10 to 100, counting by 10?
1
2
3
4
5

import numpy as np
# How would you create a one dimensional NumPy array of the numbers from 10 to 100, counting by 10?
np.arange(10, 110, 10)
# array([ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100])

 How could you do the same thing with a standard Python range and a list?
1
2
3
4

# How could you do the same thing with a standard Python range and a list?
np.array([i for i in range(10, 110, 10)])
# array([ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100])

 What does np.array() do (no arguments passed to constructor). Guess: exception?
1
2
3

# What does np.array() do (no arguments passed to constructor). Guess: exception?
# np.array()

 How might you construct a NumPy array of capital letters (AZ)?
1
2
3
4
5
6
7
8
9

# How might you construct a NumPy array of capital letters (AZ)
arr = np.array([chr(i) for i in range(ord('A'), ord('Z') + 1)])
arr.dtype
arr[0].dtype
arr
# array(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
# 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
# dtype='<U1')
# dtype('<U1')

 How would you create a tenelement array of all zeros?
1
2
3

# How would you create a tenelement array of all zeros?
print(np.zeros(10))
# [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

 What is the default data dype for the np.zeros function?
 How would you find the data type given in #6.
1
2
3
4
5

# What is the default data dype for the np.zeros function?
# Guess is float64
df = np.zeros(10)
df.dtype
# dtype('float64')

 What function would return the same number of elements, but of all ones?
1
2
3

# Of all ones?
print(np.ones(10))
# [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]

 How could you create a ten element array of random integers between 1 and 5 (inclusive)?
1
2
3

# How can you create an array of 10 random integers?
np.random.randint(1, 6, 10)
# array([3, 3, 1, 1, 2, 3, 2, 4, 1, 3]) (generated random integer numbers)

 How can you create a normal distribution of 10 numbers, centered on 5?
1
2
3
4
5
6

# How can you create a normal distribution of 10 numbers, centered on 5?
# Note, the 1 in center represents mu, size of STD DEV, and is arbitrary.
np.random.normal(5, 1, 10)
#array([5.18222846, 5.21652635, 4.59808486, 3.85088095, 4.09221797,
# 4.78478114, 7.09477432, 4.40780258, 4.05767913, 5.1786815 ])

 How can you create an array of 10 random numbers in the range 0  1?
1
2
3
4
5

# How can you create an array of 10 random numbers in the range 0  1?
np.random.rand(10)
# array([0.61750905, 0.08361662, 0.79065758, 0.68666014, 0.35441328,
# 0.90013653, 0.0342614 , 0.71401805, 0.74200534, 0.14737658])

 Consider the code:
np.ones((3,5))
and np.zeros((3,5)))
. Does this A) create an array of three arrays containing five elements each or B) create an array of five arrays containing three elements each?
1
2
3
4

np.zeros((3, 5))
# array([[0., 0., 0., 0., 0.],
# [0., 0., 0., 0., 0.],
# [0., 0., 0., 0., 0.]])

 Consider an array named
myarray
that is displayed as in the block below. What value does the code myarray[1,2]
return? A) 10 B) 7.
1
2
3
4
5
6
7

myarray = np.arange(1, 13).reshape(3, 4)
myarray
# array([[ 1, 2, 3, 4],
# [ 5, 6, 7, 8],
# [ 9, 10, 11, 12]])
myarray[1,2]
# 7

 Given myarray as shown above, what is the value of myarray.ndim?
 An array of three arrays of four elements each like this has twelve elements, of course. How could you create a new array consisting of two arrays of six elements each?
1
2
3
4

myarray1 = myarray.reshape(2,6)
print(myarray1)
# array([[ 1, 2, 3, 4, 5, 6],
# [ 7, 8, 9, 10, 11, 12]])

 Given myarray from #13, and the code
x = myarray
, what would x[0,0] == 42
do?
1
2

myarray.shape
# (3, 4)

1
2
3
4
5
6
7
8
9

myarray
# array([[ 1, 2, 3, 4],
# [ 5, 6, 7, 8],
# [ 9, 10, 11, 12]])
x = myarray
x
# array([[ 1, 2, 3, 4],
# [ 5, 6, 7, 8],
# [ 9, 10, 11, 12]])

1
2
3
4
5

x[0,0] = 42
myarray
# array([[42, 2, 3, 4],
# [ 5, 6, 7, 8],
# [ 9, 10, 11, 12]])

 How could you create a twodimensional, 3 x 4 array (three arrays of four elements each) with random numbers from 1 to 10?
1
2
3
4
5

# Create a 3x4 array of random integers between 1 and 10
np.random.randint(1, 11, (3,4))
# array([[ 9, 9, 10, 8],
# [ 7, 6, 10, 7],
# [ 4, 1, 3, 3]])

 How could you create an array of the same size as #17, filled with zeros.
1
2
3
4
5
6
7
8
9

arr = np.random.randint(1,11,12).reshape(3,4)
arr
# array([[ 3, 2, 1, 5],
# [10, 1, 4, 7],
# [ 4, 2, 2, 2]])
arr  arr
# array([[0, 0, 0, 0],
# [0, 0, 0, 0],
# [0, 0, 0, 0]])

 What would
x_array.shape()
return?
1
2
3
4
5
6
7
8

z_list = [z for z in range(0,5)]
y_list = [z_list for y in range(0,4)]
x_list = [y_list for x in range(0,3)]
x_array = np.array(x_list)
# My guess is x_array.shape == 3,4,5. Correct but show tuple brackets would be better
x_array.shape
# (3, 4, 5)

 Given x_array from #19, what is the value for
x_array.ndim
?
1
2
3

# What is the value of x_array.ndim ?
x_array.ndim
# 3

 Given an array, named “arr“, that looks like:
1
2
3
4
5
6
7
8
9
10
11
12

# Given the following:
arr = np.arange(0,6).reshape(2,3)
arr
# How could you convert it to an array that looks like
# array([[0,3], [1,4], [2,5]))
# My answer either arr.transpose() or arr.T
# (arr.transpose() == arr.T).all()
# Note difference is mutablity? NO! Both return a view. Need to copy.
arr.transpose()
# array([[0, 3],
# [1, 4],
# [2, 5]])

 Write an expression to return the first row. (It will be a fiveelement array).
 Write an expression to return the last row. (It will be a fiveelement array).
1
2
3
4
5
6

four_by_five = np.arange(1, 21).reshape(4,5)
four_by_five
# array([[ 1, 2, 3, 4, 5],
# [ 6, 7, 8, 9, 10],
# [11, 12, 13, 14, 15],
# [16, 17, 18, 19, 20]])

1
2
3
4
5
6

# Write an exoression to return the first row
four_by_five[0]
# array([1, 2, 3, 4, 5])
# Write an exoression to return the last row
four_by_five[1]
# array([16, 17, 18, 19, 20])

 What does
four_by_five[2,3]
return?
 What does
four_by_five[3,2]
return?
1
2
3
4
5
6

# What does four_by_five[2,3] return? My answer, 14 (scalar)
four_by_five[2,3]
# 14
# What does four_by_five[3,2] return? My answer, 18 (scalar)
four_by_five[3,2]
# 18

 How could you return the first column? It will be a (fourelement array ending with 16.)
1
2
3

# How could you return the first column? It will be a (fourelement array ending with 16.) My answer four_by_five[:,0]
four_by_five[:,0]
# array([ 1, 6, 11, 16])

 What does
four_by_five[:, 3:5]
return?
1
2
3
4
5
6
7
8
9
10
11
12
13

# What does four_by_five[:, 2:4] return?
# My answer the last two columns  wrong, third and fourth columns
four_by_five[:, 2:4]
# array([[ 3, 4],
# [ 8, 9],
# [13, 14],
# [18, 19]])
# What does four_by_five[:, 3:5] return?
four_by_five[:, 3:5]
# array([[ 4, 5],
# [ 9, 10],
# [14, 15],
# [19, 20]])

 Write an expression to return the last two columns of the middle two rows.
1
2
3
4

# Write an expression to return the last two columns of the middle two rows.
four_by_five[1:3, 3:]
# array([[ 9, 10],
# [14, 15]])

 What would be the result of
one_dim * 2
?
1
2
3
4
5
6
7

one_dim = np.arange(1,6)
one_dim
# array([1, 2, 3, 4, 5])
# What would be the result of one_dim * 2
# My answer array([2, 4, 6, 8, 10])
one_dim * 2
# array([ 2, 4, 6, 8, 10])

 What would be returned by this expression:
one_dim + np.arange(5, 0, 1)
?
1
2
3
4

# What would be the result of one_dim + np.arange(5, 0, 1)?
# My answer: array([ 6, 6, 6, 6, 6])
one_dim + np.arange(5, 0, 1)
# array([6, 6, 6, 6, 6])

 How many zeros are in the array returned by
one_dim  one_dim
?
1
2
3
4

# How many zeros are in the array returned by one_dim  one_dim ?
# My answer: 5
one_dim  one_dim
# array([0, 0, 0, 0, 0])

 What is the result of
one_dim > 2
?
1
2
3
4

# What is the result of one_dim > 2 ?
# My answer: array([F, F, T, T, T]) (abbreviated)
one_dim > 2
# array([False, False, True, True, True])

 For NumPy arrays, logical operations are done with the operators “&” and ““, rather than the usual Python “and” and “or”. Given that, what would be the result of this expression?
1
2
3
4
5
6

# For NumPy arrays, logical operations are done with the operators "&" and "",
# rather than the usual Python "and" and "or". Given that, can you evaluate this expression?
# (one_dim > 4)  (one_dim == 1)
# My answer: array([True, False, False, False, True])
(one_dim > 4)  (one_dim == 1)
# array([ True, False, False, False, True])

 What is the result of this expression:
one_dim
1
2
3
4

# What is the result of one_dim?
# My answer array([1, 2, 3, 4, 5])
one_dim
# array([1, 2, 3, 4, 5])

np.absolute
take the absolute value of each element. Given that, what would the result be of the following expression: np.absolute((one_dim[3:])
1
2
3
4

# np.absolute take the absolute value of each element. Given that, what would the result be of the following expression:
# My answer 4,5
np.absolute((one_dim[3:]))
# array([4, 5])

 This exercise and #36 deal with sequence functions, which operate on the whole array rather than perelement. What is returned by
one_dim.sum()
?
1
2
3
4
5
6
7
8

# What is returned by one_dim.sum()?
# My answer: 15
one_dim.sum()
# 15
# What is the value of one_dim.mean() ?
print(one_dim) # [1 2 3 4 5]
one_dim.mean() # The median!
# 3.0

 What are the values for:
np.around(np.sin(arr), 0)
1
2
3
4
5
6
7
8
9

# Given the following...
arr = np.array([0., .5, 1.0, 1.5, 2.0]) * np.pi
arr
# array([0. , 1.57079633, 3.14159265, 4.71238898, 6.28318531])
# What are the "approximate" values for
# np.around(np.sin(arr), 0)
# My answer: array(0, 1, 0, 1, 0)
np.around(np.sin(arr), 0)
# array([ 0., 1., 0., 1., 0.])

 For the defined above in #36, what are the values for:
np.around(np.cos(arr), 0)
1
2
3
4
5

# What are the approximate values for
# np.around(np.cos(arr), 0)
# My answer: array(1, 0, 1, 0, 1)
np.around(np.cos(arr), 0)
# array([ 1., 0., 1., 0., 1.])

 You’re asked to save the following two arrays as is to a file,
data.npz
. The arrays should be named as they are here in the file. How could you do it?
1
2
3
4
5

# You're asked to save the following two arrays as is to a file, "data.npz". The arrays should be named as they are here in the file. How could you do it?
people = np.array(["John", "Jenniffer", "Helen", "Miryam"])
languages = np.array([2, 2, 1, 1])
# My answer np.savez("data.npz", people=people, languages=languages)
np.savez("data.npz", people=people, languages=languages)

 Assuming you saved the file,
data.npz
, in #39, how could you reload the arrays into two new variables: people2
and languages2
?
1
2
3
4
5
6
7
8

# How could you load the files again into two new variables, people2 and languages2
arrays = np.load("data.npz")
people2 = arrays["people"]
languages2 = arrays["languages"]
print(people2)
print(languages2)
# ['John' 'Jenniffer' 'Helen' 'Miryam']
# [2 2 1 1]

 Given:
arr = np.arange(1,13).reshape(3,4)
; How could you save it to a CSV file, myrray.csv
.
1
2
3
4
5

# Given
# arr = np.arange(1,13).reshape(3,4)
# Save it to a csv file, "myrray.csv".
arr = np.arange(1,13).reshape(3,4)
np.savetxt("myarray.csv", arr, delimiter=",")

 Given the CSV file saved in #41, how could you load it back into a variable,
arr2
?
1
2
3
4
5
6
7

# How would you load it back into arr2?
# My guess: arr2 = np.loadtxt("myarray.csv", delimiter=",")
arr2 = np.loadtxt("myarray.csv", delimiter=",")
arr2
# array([[ 1., 2., 3., 4.],
# [ 5., 6., 7., 8.],
# [ 9., 10., 11., 12.]])

 What would you expect the value of
np.char.capitalize(lumberjack)[2]
to be?
1
2
3
4

# Given
lumberjack = np.array("I'm a lumberjack and I'm OK I sleep all night and I work all day".split(" "))
lumberjack
# array(["I'm", 'a', 'lumberjack', 'and',"I'm", 'OK', 'I', 'sleep', 'all', 'night', 'and', 'I', 'work', 'all', 'day'], dtype='<U10')

1
2
3
4

# How could you capitalize the first character of each string?
# Guessed np.capitalize(lumberjack) wrong
np.char.capitalize(lumberjack)
# array(["I'm", 'A', 'Lumberjack', 'And', "I'm", 'Ok', 'I', 'Sleep', 'All', 'Night', 'And', 'I', 'Work', 'All', 'Day'], dtype='<U10')

1
2
3
4

# What would you expect the value of np.char.capitalize(lunberjack)[2] to be?
# My answer "Lumberjack"
np.char.capitalize(lumberjack)[2]
# 'Lumberjack'

 How could you surround each string with an initial and final asterisk character (*)?
1
2
3
4

# How could you surround each string with an initial and final asterisk character (*)?
# Guessed add takes n arguments, wrong, need two arguments at a time
np.char.add(np.char.add("*", lumberjack), "*")
# array(["*I'm*", '*a*', '*lumberjack*', '*and*', "*I'm*", '*OK*', '*I*', '*sleep*', '*all*', '*night*', '*and*', '*I*', '*work*', '*all*','*day*'], dtype='<U12')

 The function,
np.where
, can be used to create an array of indexes that can be used to index into the original array to subset an array based on a condition. Given that background, can you evaluate the following?
1
2
3
4

# np.where can be used to make selections. How can we use this to create a smaller array of those strings that have a length >= 5?
# My guess np.where(lumberjack, np.length(lumberjack) >= 5) Way off.
np.where(np.char.str_len(lumberjack) >=5)
# (array([2, 7, 9]),)

1
2

lumberjack[np.where(np.char.str_len(lumberjack) >=5)]
# array(['lumberjack', 'sleep', 'night'], dtype='<U10')

Solution ^{2}