NumPy Exercises Solutions

These are my solutions that I wrote while working on the article NumPy Examples: Forty-Five Practice Questions To Make You an Expert. I’ve tried to list the original questions in the comments.

import numpy as np

Array Creation

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?

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?

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?

# np.array()
# How might you construct a NumPy array of capital letters (A-Z) 
arr = np.array(['fee', 'fi', 'fo', 'fumble-dee-dum'])
arr.dtype
dtype('<U14')
arr = np.array([chr(i) for i in range(ord('A'), ord('Z') + 1)])
arr.dtype
arr[0].dtype
dtype('<U1')
# How would you create a ten-element array of all zeros?  
print(np.zeros(10))

# Of all ones?
print(np.ones(10))
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
# What is the default data dype for the np.zeros function?
# Guess is float64

df = np.zeros(10)
df.dtype
dtype('float64')
# How can you create an array of 10 random integers?

np.random.randint(1, 6, 10)
array([3, 4, 4, 4, 5, 1, 1, 1, 2, 5])
# 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([6.85778263, 4.30479282, 5.81265723, 2.69949502, 5.40802936,
       4.04006003, 4.23499929, 5.98175567, 4.92540968, 4.77301553])
# How can you create an array of 10 random numbers in the range 0 - 1?

np.random.rand(10)
array([0.3186166 , 0.64290918, 0.50260013, 0.94563704, 0.52212559,
       0.19816035, 0.00424413, 0.93909078, 0.07028394, 0.55817247])

Multidimensional arrays

np.zeros((3, 5))
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])
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
myarray.ndim
2
myarray.reshape(2,6)
array([[ 1,  2,  3,  4,  5,  6],
       [ 7,  8,  9, 10, 11, 12]])
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')
myarray.shape
(3, 4)
myarray.reshape(2,6)
array([[ 1,  2,  3,  4,  5,  6],
       [ 7,  8,  9, 10, 11, 12]])
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]])
x[0,0] = 42
myarray
array([[42,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])
# Create a 3x4 array of random integers between 1 and 10 
np.random.randint(1, 11, (3,4))
array([[9, 8, 7, 4],
       [3, 5, 8, 2],
       [5, 3, 5, 6]])
# ... or:
    
arr = np.random.randint(1,11,12).reshape(3,4)
arr
array([[ 1,  8,  9,  1],
       [10,  9,  9,  5],
       [ 6, 10,  8,  4]])
arr - arr
array([[0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])
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)
# What is the value of x_array.ndim?
x_array.ndim
3
# 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]])
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]])
# 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?  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 (four-element array ending with 16.) My answer four_by_five[:,0]
four_by_five[:,0]
array([ 1,  6, 11, 16])
# 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]])
# Corrected question
# 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.
four_by_five[1:3, 3:] 
array([[ 9, 10],
       [14, 15]])
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 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 ?
# My answer: 5
one_dim - one_dim
array([0, 0, 0, 0, 0])
# 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, 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 -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:
# My answer 4,5
np.absolute(-(one_dim[3:]))
array([4, 5])
# 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)
one_dim.mean() # The median!
[1 2 3 4 5]
3.0
# 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.])
# 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?
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)
# 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)
# Save it to a csv file, "myrray.csv".
arr = np.arange(1,13).reshape(3,4)
np.savetxt("myarray.csv", arr, delimiter=",")
# 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.]])
# 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')
# 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')
# 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 (*)?  
# 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')
# 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]),)
lumberjack[np.where(np.char.str_len(lumberjack) >=5)]
array(['lumberjack', 'sleep', 'night'], dtype='<U10')