Wednesday, October 7th, 2026¶
Last class we discussed taking more control of figure generation using matplotlib.pyplot. In particular:
- The
plt.figurefunction can be used to manually create a figure object to plot on.- The optional argument
figsizecan be included to change the size of the figure. - Generally, only one figure should be created per code cell.
- The optional argument
- The
plt.subplotfunction can be used to add anaxesobject to a figure.- The optional argument
aspect='equal'can be used to force a $1:1$ aspect ratio. - The call
plt.subplot(r,c,n)will create a subplot as part of arbycgrid (i.e.rrows andccolumns) in thenth position (starting with1in the top left and proceeding left-to-right, top-to-bottom).
- The optional argument
List unpacking¶
Suppose we have a list of items and we wish to assign each element in the list to a given variable name.
For example, suppose we have a list [3,4,5] and we would like to assign the variables a, b, and c to store these three values respectively.
my_list = [3,4,5]
a = my_list[0]
b = my_list[1]
c = my_list[2]
print(b)
4
Alternatively, Python allows us to make a simultaneous assignment of variable names to values in a list by setting a comma-separated sequence of variable names equal to the list. That is, something like variable1, variable2, variable3, variable4 = <list of length 4>.
my_list = [3,4,5]
a,b,c = my_list
print(c)
5
This can and should be used to help with readability of code. For example, suppose we want to iterate through a list of Pythagorean triples and perform some operations on the $a$ and $b$ parts of each triple.
ptriples = [[3, 4, 5],
[4, 3, 5],
[5, 12, 13],
[6, 8, 10],
[8, 6, 10],
[8, 15, 17],
[9, 12, 15],
[12, 5, 13],
[12, 9, 15],
[12, 16, 20],
[15, 8, 17],
[15, 20, 25],
[16, 12, 20],
[20, 15, 25]]
for ptriple in ptriples:
a = ptriple[0]
b = ptriple[1]
c = ptriple[2]
print(a)
3 4 5 6 8 8 9 12 12 12 15 15 16 20
for a,b,c in ptriples:
print(a)
3 4 5 6 8 8 9 12 12 12 15 15 16 20
def f():
return 2, 'hello'
f()
(2, 'hello')
n, s = f()
print(n)
print(s)
2 hello
More with numpy¶
We have started looking at using numpy arrays to perform iterative calculations quickly. For example, we've used np.linspace to generate an array of values that can be plugged into a function that performs some arithmetic element-by-element. For example, earlier today we generated an array of $t$-values and evaluated $\sin t$ and $\cos t$ using numpy.
However, numpy arrays are far more flexible.
Multi-dimensional arrays¶
It is often very useful to represent higher-dimensional data as a numpy array.
There are many ways to generate multi-dimensional arrays with numpy. For example, we can reshape a 1D array into a compatible 2D shape using the .reshape method. The .reshape method takes in a sequence of integers that define the shape of the output array. For example, calling .reshape(2,5) on an array of length 10 will create an array containing 2 rows and 5 columns.
import numpy as np
my_array = np.arange(10)
print(my_array)
[0 1 2 3 4 5 6 7 8 9]
my_2d_array = my_array.reshape(2,5)
print(my_2d_array)
[[0 1 2 3 4] [5 6 7 8 9]]
my_array.reshape(3,5)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[18], line 1 ----> 1 my_array.reshape(3,5) ValueError: cannot reshape array of size 10 into shape (3,5)
Just like with 1D arrays, we can perform arithmetic operations elementwise on 2D arrays.
print(my_2d_array)
print(my_2d_array + 5)
[[0 1 2 3 4] [5 6 7 8 9]] [[ 5 6 7 8 9] [10 11 12 13 14]]
print(my_2d_array*7)
[[ 0 7 14 21 28] [35 42 49 56 63]]
print(my_2d_array / 2)
[[0. 0.5 1. 1.5 2. ] [2.5 3. 3.5 4. 4.5]]
Each array has an attribute .shape that stores the shape (i.e. number of rows, columns, etc.) of the array.
my_array.shape
(10,)
my_2d_array.shape
(2, 5)
np.arange(100).reshape(5,2,10).shape
(5, 2, 10)
We can also use np.ones or np.zeros, passing in a tuple (e.g. np.ones((3,2))) to generate multi-dimensional arrays with the input shape.
np.ones(10)
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
np.ones((5,2))
array([[1., 1.],
[1., 1.],
[1., 1.],
[1., 1.],
[1., 1.]])
np.zeros((10,3))
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
We've previously seen that we can use the np.array function to convert a list of integers/floats into an array. We can also use np.array to convert a list of lists into an array.
Note: This only works if each "inner" list has the same length.
list_of_lists = [[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]]
print(list_of_lists)
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
my_2d_array = np.array(list_of_lists)
print(my_2d_array)
[[ 1 2 3] [ 4 5 6] [ 7 8 9] [10 11 12]]
With multi-dimensional arrays, we can slice across any axis of the array. This works just like regular list/array slicing, except that we can separately slice through a row, columm, or any other axis. We use commas inside the slice to separate between different dimensions of the array. For example, taking [:,0] will produce a slice consisting of elements from every row (the first dimension), but only the first column (e.g. the index-0 entry of the second dimension, i.e. the columns).
print(my_2d_array[:, 0])
[ 1 4 7 10]
print(my_2d_array[:, 1])
[ 2 5 8 11]
print(my_2d_array[2, :])
[7 8 9]
print(my_2d_array[2, 1])
8
print(my_2d_array[:2, -2:])
[[2 3] [5 6]]
As another example, consider a list of lists of Pythagorean triples $(a,b,c)$.
ptriples = [[3, 4, 5],
[4, 3, 5],
[5, 12, 13],
[6, 8, 10],
[8, 6, 10],
[8, 15, 17],
[9, 12, 15],
[12, 5, 13],
[12, 9, 15],
[12, 16, 20],
[15, 8, 17],
[15, 20, 25],
[16, 12, 20],
[20, 15, 25]]
We've previously discussed how we may want to select just the $a$ and $b$ parts of each triple so that we can plot them against one another. This can be done using list comprehension or by initializing empty lists and building them up. What if we converted this list of lists into a numpy array?
ptriples_array = np.array(ptriples)
print(ptriples_array)
[[ 3 4 5] [ 4 3 5] [ 5 12 13] [ 6 8 10] [ 8 6 10] [ 8 15 17] [ 9 12 15] [12 5 13] [12 9 15] [12 16 20] [15 8 17] [15 20 25] [16 12 20] [20 15 25]]
a = ptriples_array[:,0]
b = ptriples_array[:,1]
import matplotlib.pyplot as plt
plt.plot(a,b,'o')
[<matplotlib.lines.Line2D at 0x193fb8f2c10>]
ptriple = [3,4,5]
pdouble = ptriple[:2]
print(pdouble)
[3, 4]
pdoubles_array = ptriples_array[:, :2]
print(pdoubles_array)
[[ 3 4] [ 4 3] [ 5 12] [ 6 8] [ 8 6] [ 8 15] [ 9 12] [12 5] [12 9] [12 16] [15 8] [15 20] [16 12] [20 15]]