This webpage is a static view of an interactive Jupyter Notebook tutorial. To get the full interactive experience where you can run Python code, modify examples and complete exercises, click the "Open in Colab" button. This will access the Google Colab notebook from a GitHub repository github.com/dchappell2/Computational-Physics and open it in Google Colab. You will need a Google account if you want to open it in Colab.
Note: You can download a pdf of the lecture slides for this chapter here: Chapter 8 slides
Goals
This chapter describes how to create, apply and extract data from multi-dimensional arrays in 2D, 3D and higher dimensions.
(n,m) tuplen specifies the number rowsm specifies the number of columns.np.zeros((n,m)) command.np.zeros() function expects.import numpy as np
A = np.zeros((2,3))
print(A)
In the following example, we fill a 2x5 array with random integers between 1 and 9 inclusive.
size=(3,5) parameter.endpoint=True parameter to tell Python to includ the upper limit (9 in this example).rng = np.random.default_rng() # create random number Generator
A = rng.integers(1, 9, size=(3,5),endpoint=True)
print(A)
Create a 2D array with 6 columns and 3 rows. Each element should be a random integer whose value satisfies $1 \leq x \leq 4$. Print the array.
# Your code here
(p,n,m) tuplep = first parameter = the number of layers p of the array.n = 2nd parameter = the number rows nm = 3rd parameter = the number of columns mA = np.zeros((4,2,3))
print(A)
NumPy provides three attributes that characterize the shape and size of NumPy arrays. Remember that attributes do no use parentheses, while methods do.
.shape[0].shape[1][2], [3], etc. positions.
A = rng.integers(1, 9, size=(3,5),endpoint=True)
print("A = ")
print(A)
print()
print("shape of A is ",A.shape)
n_rows = A.shape[0] # extract the number of rows
n_cols = A.shape[1] # extract the number of columns
print("number of rows in A =",n_rows)
print("number of columns in A =",n_cols)
.size returns the total number of elements in A, which equals the (number of rows) $\times$ (number of columns) for a 2D array.ndim returns the number of dimensions, which is 2 for a 2D array, 3 for a 3D array, etc.print("size of A (total # elements) =",A.size)
print("number of dimensions of A =",A.ndim)
Here's an example of creating a 4D array:
z = np.zeros((2,3,4,5))
print("shape of z (length along each axis) =",z.shape)
print("size of z (total # elements) =",z.size)
print("number of dimensions of A =",z.ndim)
print()
print("z = ")
print(z)
The following examples show how to access and slice a 2D array.
rng = np.random.default_rng() # create random number Generator
A = rng.integers(1, 9, size=(3,5),endpoint=True)
print("A = ")
print(A) # prints array A
print() # prints a blank line
print("A[0,2] = ",A[0,2]) # top row, 3rd column
print("A[0,:2] = ",A[0,1:3]) # top row, columns 2 and 3
print("A[0,:] = ",A[0,:]) # top row
print("A[0,:] = ",A[:,1]) # second column
print()
print("A[0:2,0:2] = ") # 2x2 matrix from top-left corner of A
print(A[0:2,0:2])
The following over-writes the top row of our 2D array with zeros.
.shape attribute to automatically determine how many columns are in A, which we pass to the np.zeros() function.A[0,:] = np.zeros(A.shape[1])
print(A)
A array defined above to 1'sA array# your code here
.shape attribute to easily create a new array with the same size as an existing array like this:A = rng.integers(1, 9, size=(3,5),endpoint=True)
B = np.zeros(A.shape) # Array B will have same size as array A
print(B)
.T after our array like this: A.TA array in the previous section:print("original Array, A:")
print(A)
print()
print("transpose of A:")
print(A.T)
Flatten
.flatten() method.print("flattened version of A")
A_flat = A.flatten()
print(A_flat)
Reshape
.reshape() method can be used to reorder the elements of an array..reshape() method takes a tuple as an argument: single number for 1D array, (n,m) for 2D array, (p,n,m) for a 3D array and so on.##### Create a 1x12 array filled with integers
print("original array. A ")
A = np.linspace(1,12,12,dtype=int)
print(A)
##### Reshape -> 2x6 (2 rows, 6 columns)
print()
print("A2 = A.reshape((2,6)) ")
A2 = A.reshape((2,6))
print(A2)
print()
##### Reshape -> 3x4 (3 rows, 4 columns)
print("A3 = A2.reshape((3,4)) ")
A3 = A2.reshape((3,4))
print(A3)
print()
##### Reshape -> 2x2x3 (2 layers, 2 rows, 3 columns) = 3D array
print("A4 = A3.reshape((2,2,3)) ")
A4 = A3.reshape((2,2,3))
print(A4)
R = np.linspace(1,15,15)
R = R.reshape((5,3))
R = R.T
print("R = ")
print(R)
ave = R.mean(axis = 0)
print()
print("Column mean = ")
print(ave)
ave = R.mean(axis = 1)
print()
print("Row mean = ")
print(ave)
Google Colab poses some challenges when reading and writing files due to the way Google handles directories. When we run Python on your laptop, this process will be much simpler.
bh_merger.csv from the Python_Tutorials directory on GitHub and save it on your laptop. This file contains the masses of binary black hole pairs that have merged and given off gravitational waves.data.data array, the data will be saved in memory, so you can run or rerun the analysis code in the following Code Cells without having to reload the file.Here's what the following Code Cell does to read in the data file:
google.files moduleuploaded = files.upload() to launch a file picker. You'll need to navigate to you the bh_merger.csv file to load it.uploaded dictionary using the command file_name = list(uploaded.keys())[0]np.loadtxt(file_name) to load a file specified by file_name.Use of the np.loadtxt() command
np.loadtxt(file_name) loads a data file with name file_name. The file must contain rows of numeric values with equal number of values per row, with each numerica value separated by spaces. The file cannot have any extra header or footer data. Thus, the file must have the form:```
1.0 2.4 3.6
3.5 0.1 0.4
4.3 2.1 3.5
```
np.loadtxt(file_name,delimiter=',').```
1.0, 2.4, 3.6
3.5, 0.1, 0.4
4.3, 2.1, 3.5
```
skiprows parameter like this: np.loadtxt(file_name, skiprows=1,delimiter=',').```
x, y, z
1.0, 2.4, 3.6
3.5, 0.1, 0.4
4.3, 2.1, 3.5
```
bh_merger.csv file has one header line and uses a comma delimiter, so we use the command data = np.loadtxt(file_name,skiprows=1,delimiter=',') to read it.# Import Libraries
from google.colab import files # used to load files in Google
import numpy as np
##### Load Data File
uploaded = files.upload() # This opens a file picker
# uploaded is a dictionary: filename -> bytes
# Get the first filename
file_name = list(uploaded.keys())[0]
# Load the data into a NumPy array
# Assuming a text file with numeric data, separated by commas
# and with one header line that must be skipped
data = np.loadtxt(file_name,skiprows=1,delimiter=',')
The bh_merger.csv file contains the following columns of data:
The following Code prints the number of rows, columns and first 5 rows of data.
# Inspect the array
nrows = data.shape[0]
ncols = data.shape[1]
print()
print(f"{file_name} contains {nrows} rows and {ncols} columns")
print()
print("First 5 rows:")
print(data[:5])
The following code shows how to extract the first column of values from the data array and name it mass1 (this will contain the masses of one of black holes in the binary system.)
mass2 (mass of second black hole)dist (distance of the black holes)mass1 = data[:,0] # mass one is stored in the first column (index = 0)
# your code here
mass1. Use the NumPy vectorized methodsmass2. Use the NumPy vectorized methods# your code here
data array to create a single array containing the masses of both black holes.mass1 and mass2?# your code here
A[1,0,3]This tutorial is an adaptation of "Python for Physicists"