# First, let's import NumPy
import numpy as npModuleNotFoundError: No module named 'numpy'
Module 3: NumPy
Python lists can store numerical data, but calculations with many values often require loops. NumPy gives us arrays that can perform the same calculation on every value at once.
NumPy (Numerical Python) is a package for numerical computing. It provides multidimensional arrays and mathematical functions designed to operate on those arrays efficiently.
# First, let's import NumPy
import numpy as npModuleNotFoundError: No module named 'numpy'
To create an array we use the function np.array(). We must pass a list or tuple to the function.
# Create a simple array from a list
ls = [1, 2, 3, 4, 5]
arr = np.array(ls)
print(arr)NameError: name 'np' is not defined
# Single line
# Create a simple array from a list
arr = np.array([1, 2, 3, 4, 5])
print(arr)NameError: name 'np' is not defined
# Tuples work too!
tup = (1, 2, 3, 4, 5)
arr = np.array(tup)
print(arr)NameError: name 'np' is not defined
# Single line
arr = np.array((1, 2, 3, 4, 5))
print(arr)NameError: name 'np' is not defined
What happens when we initialize a NumPy array with a set?
The np.array documentation says that the object argument must be “an array, any object exposing the array interface, an object whose __array__ method returns an array, or any (nested) sequence”.
A set is not a sequence. It is unordered and does not support indexing. NumPy therefore treats the complete set as one Python object instead of turning its members into array elements.
# This creates a zero-dimensional object array, not five integer elements.
arr = np.array({1, 2, 3, 4, 5})
print(arr)
print(arr.shape)
print(arr.dtype)NameError: name 'np' is not defined
What will be the value of arr? Which value type will their elements have?
arr = np.array((1, 2.0, 3))
print(arr)NameError: name 'np' is not defined
The elements of the array will all be of type float64. NumPy automatically upcasts the integer values to floats so the full array has a single consistent data type.
What will be the value of arr? Which value type will their elements have?
arr = np.array(1, 2.0, 3)
print(arr)This code raises an error. The np.array function expects one main object argument, typically a list or tuple, but here it receives three separate values instead.
Every NumPy array has one data type, available through its dtype property. NumPy supports many types, including booleans, integers, floating-point numbers, complex numbers, and strings. When the input mixes types, NumPy chooses one type capable of representing every value.
# Array of strings
a = np.array(["a", "b", "c"])
print(a)NameError: name 'np' is not defined
# Array of floats
a = np.array([1, 2.2, 3.3])
# Notice how '1' is turned into a float '1.'
print(a)NameError: name 'np' is not defined
# Mixed array
a = np.array([1, "two", 3])
# Notice that '1' and '3' are turned into strings!
print(a)NameError: name 'np' is not defined
We can specify the NumPy array type in the second argument of np.array().
a = np.array([1, 2, 3], float)
print(a)NameError: name 'np' is not defined
a = np.array([1, 2, 3], str)
print(a)NameError: name 'np' is not defined
Nested list are used to create multi-dimensional arrays.
# Create a 2D array (Matrix)
# We will use nested lists
row_0 = [1, 2, 3]
row_1 = [4, 5, 6]
row_2 = [7, 8, 9]
ls_matrix = [row_0, row_1, row_2]
matrix = np.array(ls_matrix)
print(matrix)NameError: name 'np' is not defined
# All nested list must have the same length!
row_0 = [1, 2, 3]
row_1 = [4, 5, 6, 0]
row_2 = [7, 8, 9]
ls_matrix = [row_0, row_1, row_2]
matrix = np.array(ls_matrix)
print(matrix)# Single line
# Create a 2D array (Matrix)
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(matrix)NameError: name 'np' is not defined
# Best format - helps clarity
# Create a 2D array (Matrix)
matrix = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print(matrix)NameError: name 'np' is not defined
In NumPy, the order of dimensions is indicated by the nesting of brackets. The outermost bracket (purple) represents the first dimension, indexed as dimension 0. The next level of brackets inside (blue) represents the second dimension, or dimension 1. If you continue adding more nested brackets, each new level represents a higher dimension. For example, the third level of brackets would be dimension 2, and so on. This hierarchical structure helps in understanding the shape and structure of multi-dimensional arrays.
How would we create a 3D matrix?
matrix_3d = np.array([
[[1, 2], [3, 4]],
[[5, 6], [7, 8]]
])
print(matrix_3d)
print(matrix_3d.shape)NameError: name 'np' is not defined
# Create an array of zeros
zeros = np.zeros(5)
print(zeros)NameError: name 'np' is not defined
# Create a 2x3 matrix of ones
shape = (2, 3)
ones = np.ones(shape)
print(ones)NameError: name 'np' is not defined
# Single line
# Create a 2x3 matrix of ones
ones = np.ones((2, 3))
print(ones)NameError: name 'np' is not defined
# Create an array of a range of numbers
range_array = np.arange(0, 10, 2) # start, stop, step
print(range_array)NameError: name 'np' is not defined
# Create an array of a range of numbers
range_array = np.linspace(0, 10, 6) # start, stop, length
print(range_array)NameError: name 'np' is not defined
Create an array containing all odd numbers between 25 and 50.
# Try it!odd_numbers = np.arange(25, 50, 2)
print(odd_numbers)NameError: name 'np' is not defined
Imagine you have a rope that is 12 meters long. You want to cut it into 7 equal lengths. Using NumPy, create an array that shows the six positions where you should make the cuts.
# Try it!cut_points = np.linspace(0, 12, 8)[1:-1]
print(cut_points)NameError: name 'np' is not defined
Eight equally spaced endpoints divide the rope into seven equal intervals. We remove the beginning and end because they are not cuts.
Unlike methods, properties don’t require parentheses when accessed. They provide insights into the attributes of the array. Here is a list of some key properties of NumPy arrays.
ndim: Indicates the number of dimensions of the array.
arr = np.zeros((5, 4))
print(arr.ndim)NameError: name 'np' is not defined
shape: Returns a tuple representing the dimensions of the array. For a matrix with n rows and m columns, the shape is (n, m).
# shape returns a tuple
print(arr.shape)NameError: name 'arr' is not defined
size: Reports the total number of elements.
print(arr.size)NameError: name 'arr' is not defined
dtype: Reports the data type used by the elements.
print(arr.dtype)NameError: name 'arr' is not defined
Indexing 1D-arrays is the same as indexing lists, tuples or strings.
arr = np.array([0, 1, 2, 3, 4, 5, 6])
# Accessing single element (0-indexed)
print(arr[2])NameError: name 'np' is not defined
Indexing multi-dimensional arrays is “similar” to indexing nested lists.
matrix = np.array([[0, 1, 2], [3, 4, 5]])
# Accessing element in 2D array (Matrix)
print(matrix[1][2]) # second row, third columnNameError: name 'np' is not defined
For NumPy arrays, we can include all indices within a single set of parentheses! This is called “indexing with a tuple”.
matrix = np.array([[0, 1, 2], [3, 4, 5]])
# Accessing element in 2D array (Matrix)
print(matrix[1, 2]) # second row, third columnNameError: name 'np' is not defined
What will Python print?
matrix = np.array([[0, 1, 2], [3, 4, 5]])
print(matrix[-1, 0])NameError: name 'np' is not defined
What happens when this code runs? Explain why.
matrix = [[0, 1, 2], [3, 4, 5]]
print(matrix[2, 1])This raises an error because lists cannot be indexed with tuples.
What will be the value of x?
arr_A = np.array([[0, 1, 2], [3, 4, 5]])
arr_B = np.array([[6, 7, 8], [9, 10, 11]])
ls_arrays = [arr_A, arr_B]
x = ls_arrays[1][0, 2]
print(x)NameError: name 'np' is not defined
Slicing NumPy arrays is the same as slicing lists.
arr = np.array([0, 1, 2, 3, 4, 5, 6])
# Accessing a slice of an array
print(arr[1:4]) # Start is inclusive, end is exclusiveNameError: name 'np' is not defined
matrix = np.array([[0, 1, 2], [3, 4, 5]])
# Accessing rows/columns of a matrix
print(matrix[:, 1]) # All rows, second columnNameError: name 'np' is not defined
matrix = np.array([[0, 1, 2], [3, 4, 5]])
print(matrix[1, :]) # Second row, all columnsNameError: name 'np' is not defined
arr = np.array([0, 1, 2, 3, 4, 5, 6])
# Using steps in slicing
print(arr[0:5:2]) # Start at 0, go to 5, step by 2NameError: name 'np' is not defined
What slicing should we take to retrieve the array [2, 4, 6]?
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])NameError: name 'np' is not defined
print(arr[2:7:2])NameError: name 'arr' is not defined
What slicing should we take to retrieve the array [7, 4, 1]?
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])NameError: name 'np' is not defined
print(arr[7:0:-3])NameError: name 'arr' is not defined
What slicing should we take to retrieve the array [2, 4, 6]?
arr = np.array([
[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]
])NameError: name 'np' is not defined
print(arr[::2, 2])NameError: name 'arr' is not defined
What slicing should we take to retrieve the following matrix?
\[\begin{pmatrix} 1 & 2\\ 3 & 4\\ 5 & 6 \end{pmatrix}\]
arr = np.array([
[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]
])NameError: name 'np' is not defined
print(arr[::2, 1:])NameError: name 'arr' is not defined
Deactivate AI assistant tools, and try the following exercises.
The reshape() method reorganizes an array without changing its values. The requested shape must contain the same number of elements as the original array.
Exercise: Create an array filled with integers ordered from 1 to 12.
arr = np.arange(1, 13)
print(arr)NameError: name 'np' is not defined
Exercise: Reshape it to a \(3 \times 4\) matrix.
arr = np.arange(1, 13).reshape(3, 4)
print(arr)NameError: name 'np' is not defined
Exercise: Print its value at the first row, fourth column.
arr = np.arange(1, 13).reshape(3, 4)
print(arr[0, 3])NameError: name 'np' is not defined
ndim, shape, size, and dtype describe an array.Explain in your own words why matrix[1, 2] works for a NumPy array but not for a nested Python list.
Work through the Session 11 homework exercises available here.