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