import numpy as np
Numpy#
NumPy (Numerical Python) is a powerful library in Python for numerical and mathematical operations. We will give a brief overview of NumPy here, feel free to look here for more details.
Arrays#
The heart of NumPy lies in the arrays. NumPy arrays are similar to Python lists, but much faster if you have a large number of elements. They have two key differences compared to Python lists:
NumPy arrays have a fixed size, you cannot directly add an element like you could in a list. Instead, you have to use a function such as
np.append, which technically create another array.NumPy arrays cannot store objects of different data types and will instead convert everything to the same data type.
These are demonstrated below.
sample_list = [1,2,3] # creating a sample list
sample_array = np.array([1,2,3]) # creating a sample array
sample_list, sample_array
([1, 2, 3], array([1, 2, 3]))
sample_list_appended = sample_list + [4] # you can append to a list by creating another list
sample_array_appended = np.append(sample_array, 4) # appending to arrays requires using a function
sample_list_appended, sample_array_appended
([1, 2, 3, 4], array([1, 2, 3, 4]))
sample_list_str = sample_list_appended + ['woah'] # lists can store different types of data
sample_array_str = np.append(sample_array_appended, 'woah') # arrays cannot, they convert everything to a string here
sample_list_str, sample_array_str
([1, 2, 3, 4, 'woah'], array(['1', '2', '3', '4', 'woah'], dtype='<U21'))
Array Operations#
You can easily do math and add/subtract arrays with scalars and with other arrays that have the same dimensions, as shown below.
np.array([1, 2, 3, 4]) + 1 # adding 1
array([2, 3, 4, 5])
np.array([1, 2, 3, 4]) * 8 # multiplying by 8
array([ 8, 16, 24, 32])
np.array([1, 2, 3, 4]) + np.array([5, 6, 7, 8]) # adding two arrays with the same dimensions
array([ 6, 8, 10, 12])
np.array([1, 2, 3, 4]) ** 2 # squaring
array([ 1, 4, 9, 16])
NumPy also has several built-in functions you can use to work on arrays of numbers; examples shown below.
sample_array_appended
array([1, 2, 3, 4])
np.sum(sample_array_appended)
10
np.mean(sample_array_appended)
2.5
np.min(sample_array_appended), np.max(sample_array_appended)
(1, 4)
np.std(sample_array_appended)
1.118033988749895
Matrices#
Moreover, you can also define matrices as 2-dimensional numpy arrays, as shown below:
first_matrix = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
first_matrix
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
You can use the .shape attribute for seeing the dimensions (number of rows/columns) of the numpy array.
first_matrix.shape
(3, 3)
The range function#
The np.arange function is very helpful for defining new arrays of numbers (read more here). Examples are shown below.
np.arange(10) #Starts at 0, ends at 9 (non-inclusive on the ending side), gives you all whole numbers
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
np.arange(0, 10, 2) # Starts at 0, ends at 9, gives you numbers in increments of 2
array([0, 2, 4, 6, 8])
np.arange(3, 8, 0.5) # Starts at 3, ends at 7.5, gives you numbers in increments of 0.5
array([3. , 3.5, 4. , 4.5, 5. , 5.5, 6. , 6.5, 7. , 7.5])
np.arange(10, 0, -2) # Starts at 10, ends at 2, gives you numbers in increments of -2
array([10, 8, 6, 4, 2])
Slicing#
With NumPy, you can use slicing to extract portions of arrays based on true/false conditions as well as indices.
If choosing to extract portions based on indices, the basic syntax often follows array[start:stop:step] (similar to Python lists). Examples are shown below.
sample_array_appended = np.array([1, 2, 3, 4])
sample_array_appended[:]
# Using just [:] gives you all the values in the array. You don't have to include the second :
# This happens because the default starting index is 0 and the default ending index is after the last element
# The default step size is 1
array([1, 2, 3, 4])
sample_array_appended[0:1] # Arrays are also 0-indexed, exclusive of the element at the `stop` index
array([1])
sample_array_appended[0:len(sample_array_appended)+1:2] # gives you every other element, starting from the first
array([1, 3])
sample_array_appended[-2:] # gives you the last 2 elements
array([3, 4])
You can also use slicing with matrices (stored as 2D arrays)
first_matrix = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
first_matrix[:,:] # You're now slicing along 2 axes (rows and columns), separated by a comma
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
first_matrix[1,:] # Returns the row at row index 1
array([4, 5, 6])
first_matrix[:,1] # Returns the column and column index 1
array([2, 5, 8])
first_matrix[0:2,1:3] # Returns all rows with row indices 0 and 1 and all columns with column indices 1 and 2
array([[2, 3],
[5, 6]])
Slicing with Booleans#
As mentioned earlier, we can also slice based on true/false conditions. Examples included below.
sample_array_appended = np.array([1, 2, 3, 4])
print(f"The original array is {sample_array_appended}")
print(f"Let's say we want to keep all values less than 3")
print(f"The filtering condition is: {sample_array_appended < 3}")
print(f"The filtered output is: {sample_array_appended[sample_array_appended < 3]}")
The original array is [1 2 3 4]
Let's say we want to keep all values less than 3
The filtering condition is: [ True True False False]
The filtered output is: [1 2]
print(sample_array_appended**2 >= 4) # The output of this is an array of true/false values
sample_array_appended[sample_array_appended**2 >= 4] # We keep all indices in the original array where the value is True
[False True True True]
array([2, 3, 4])