# 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 ?
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:
np.absolute(-(one_dim[3:]))

array([4, 5])

# What is returned by one_dim.sum()?
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

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

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?
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

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')