Introduction to Matrices in NumPy¶

Matrices are a fundamental data structure in scientific computing, and numpy provides powerful tools for creating and manipulating matrices. This guide will introduce the basics of working with matrices in numpy by covering the following topics:

  1. Creating Matrices
  2. Accessing Elements
  3. Basic Matrix Operations
  4. Extracting Rows and Columns
  5. Row and Column Operations

You should read the guide carefully and run the code cells. Feel free to edit individual cells for experimentation.

(This guide was created by ChatGPT and edited by Dr. White)

1. Creating Matrices¶

In numpy, matrices are created as 2D arrays. Here are several ways to create them:

In [49]:
import numpy as np

a. Creating a Matrix from a List of Lists¶

In [50]:
# Create a 3x3 matrix of ints
matrix = np.array([[1, 2, 3], 
                   [4, 5, 6], 
                   [7, 8, 9]])
matrix
Out[50]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
In [51]:
# Create a 3x3 matrix with 64-bit float data types
matrix = np.array([[1, 2, 3], 
                   [4, 5, 6], 
                   [7, 8, 9]], np.float64)
matrix
Out[51]:
array([[1., 2., 3.],
       [4., 5., 6.],
       [7., 8., 9.]])

b. Creating Matrices with Built-in Functions¶

In [52]:
# Create a 3x3 matrix of zeros
zeros_matrix = np.zeros((3, 3))

# Create a 3x3 matrix of ones
ones_matrix = np.ones((3, 3))

# Create a 3x3 identity matrix
identity_matrix = np.eye(3)

# Create a 3x3 matrix with random values
random_matrix = np.random.rand(3, 3)

zeros_matrix, ones_matrix, identity_matrix, random_matrix
Out[52]:
(array([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]]),
 array([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]]),
 array([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]]),
 array([[0.50558483, 0.2196942 , 0.31737642],
        [0.19903738, 0.64341035, 0.35023278],
        [0.78284042, 0.89652682, 0.94573111]]))

2. Accessing Elements¶

You can access elements, rows, or columns of a matrix using indexing and slicing:

a. Accessing Individual Elements¶

In [53]:
# Access element at row 1, column 2 (remember, indexing starts from 0)
element = matrix[1, 2]
element
Out[53]:
6.0

b. Accessing Rows and Columns¶

In [54]:
# Access the second row (index 1)
second_row = matrix[1, :]

# Access the third column (index 2)
third_column = matrix[:, 2]

second_row, third_column
Out[54]:
(array([4., 5., 6.]), array([3., 6., 9.]))

c. Modifying parts of a matrix¶

In [55]:
matrix_2 = matrix
matrix_2[1,:] = matrix_2[1,:] + 1
matrix, matrix_2
Out[55]:
(array([[1., 2., 3.],
        [5., 6., 7.],
        [7., 8., 9.]]),
 array([[1., 2., 3.],
        [5., 6., 7.],
        [7., 8., 9.]]))

d. Matrix references¶

Notice the above matrix_2 copied a reference to matrix so any change to one changed both. To duplicate a matrix you need to create a new matrix. Notice the two are different in the following cell.

In [56]:
matrix_2 = np.array(matrix)
matrix_2[1,:] = matrix_2[1,:] / 100
matrix, matrix_2
Out[56]:
(array([[1., 2., 3.],
        [5., 6., 7.],
        [7., 8., 9.]]),
 array([[1.  , 2.  , 3.  ],
        [0.05, 0.06, 0.07],
        [7.  , 8.  , 9.  ]]))

3. Basic Matrix Operations¶

NumPy allows you to perform various matrix operations easily.

a. Matrix Addition and Subtraction¶

In [57]:
# Add two matrices
result_add = matrix + identity_matrix

# Subtract two matrices
result_subtract = matrix - identity_matrix

result_add, result_subtract
Out[57]:
(array([[ 2.,  2.,  3.],
        [ 5.,  7.,  7.],
        [ 7.,  8., 10.]]),
 array([[0., 2., 3.],
        [5., 5., 7.],
        [7., 8., 8.]]))

b. Matrix Multiplication¶

In [59]:
# Element-wise multiplication
element_wise_product = matrix * matrix

# Matrix multiplication, two ways
matrix_product = np.dot(matrix, identity_matrix)
mp = matrix @ identity_matrix

element_wise_product, matrix_product, mp
Out[59]:
(array([[ 1.,  4.,  9.],
        [25., 36., 49.],
        [49., 64., 81.]]),
 array([[1., 2., 3.],
        [5., 6., 7.],
        [7., 8., 9.]]),
 array([[1., 2., 3.],
        [5., 6., 7.],
        [7., 8., 9.]]))

c. Transpose of a Matrix¶

In [60]:
# Transpose the matrix
transpose_matrix = matrix.T
transpose_matrix
Out[60]:
array([[1., 5., 7.],
       [2., 6., 8.],
       [3., 7., 9.]])

d. Determinant and Inverse¶

In [61]:
# Calculate the determinant
determinant = np.linalg.det(matrix)

# Calculate the inverse (if the matrix is invertible)
inverse_matrix = np.linalg.inv(matrix) if determinant != 0 else None

determinant, inverse_matrix
Out[61]:
(-5.329070518200744e-15,
 array([[ 3.75299969e+14, -1.12589991e+15,  7.50599938e+14],
        [-7.50599938e+14,  2.25179981e+15, -1.50119988e+15],
        [ 3.75299969e+14, -1.12589991e+15,  7.50599938e+14]]))

4. Extracting Rows and Columns¶

a. Extracting Rows¶

In [62]:
# Extract the first row (index 0)
first_row = matrix[0, :]
first_row
Out[62]:
array([1., 2., 3.])

b. Extracting Columns¶

In [64]:
# Extract the second column (index 1)
second_column = matrix[:, 1]

# Extract the last column (index -1)
last_column  = matrix[:,-1]

second_column, last_column
Out[64]:
(array([2., 6., 8.]), array([3., 7., 9.]))

c. Extracting Submatrices¶

In [65]:
# Extract a 2x2 submatrix from the top-left corner
submatrix = matrix[0:2, 0:2]
submatrix
Out[65]:
array([[1., 2.],
       [5., 6.]])

5. Row and Column Operations¶

a. Sum, Mean, and Other Operations on Rows/Columns¶

In [66]:
# Sum of each row
row_sum = np.sum(matrix, axis=1)

# Mean of each column
column_mean = np.mean(matrix, axis=0)

row_sum, column_mean
Out[66]:
(array([ 6., 18., 24.]), array([4.33333333, 5.33333333, 6.33333333]))

b. Adding Rows/Columns¶

In [67]:
# Add a row (shape should match)
new_matrix_row = np.vstack([matrix, [10, 11, 12]])

# Add a column (shape should match)
new_matrix_column = np.hstack([matrix, [[10], [11], [12]]])

new_matrix_row, new_matrix_column
Out[67]:
(array([[ 1.,  2.,  3.],
        [ 5.,  6.,  7.],
        [ 7.,  8.,  9.],
        [10., 11., 12.]]),
 array([[ 1.,  2.,  3., 10.],
        [ 5.,  6.,  7., 11.],
        [ 7.,  8.,  9., 12.]]))

c. Deleting Rows/Columns¶

In [68]:
# Delete the first row (index 0)
matrix_without_first_row = np.delete(matrix, 0, axis=0)

# Delete the second column (index 1)
matrix_without_second_column = np.delete(matrix, 1, axis=1)

matrix_without_first_row, matrix_without_second_column
Out[68]:
(array([[5., 6., 7.],
        [7., 8., 9.]]),
 array([[1., 3.],
        [5., 7.],
        [7., 9.]]))

d. Replacing Rows/Columns¶

In [69]:
# Replace the first row
matrix[0, :] = [10, 11, 12]

# Replace the third column
matrix[:, 2] = [13, 14, 15]

matrix
Out[69]:
array([[10., 11., 13.],
       [ 5.,  6., 14.],
       [ 7.,  8., 15.]])