5  Matrices

Introduction

A matrix is a series of numbers arranged in rows and columns. We usually abbreviate matrices with a bolded uppercase letter:

\mathbf{A}_{j \times k} = \begin{bmatrix} a_{1,1} & a_{1,2} & \cdots & a_{1,k} \\ a_{2,1} & a_{2,2} & \cdots & a_{2,k} \\ \vdots & \vdots & \ddots & \vdots \\ a_{j,1} & a_{j,2} & \cdots & a_{j,k} \end{bmatrix}

For example,

\mathbf{A} = \begin{bmatrix} 1&2&3&4\\ 5&6&7&8\\ 9&10&11&12 \end{bmatrix}

To make a matrix in R, there are many possibilities. For the sake of simplicity, I will recommend using the matrix function with the byrow option set to TRUE.

The matrix function takes a vector and converts it to a matrix. By default, the matrix function assumes that the vector is a single column. For example,

matrix(1:4)
     [,1]
[1,]    1
[2,]    2
[3,]    3
[4,]    4

By setting the nrow (number of rows) or ncol (number of columns), the matrix dimensions are set. For example,

matrix(1:4, ncol = 2)
     [,1] [,2]
[1,]    1    3
[2,]    2    4

Note that the default is to fill in the matrix by columns. If you want it to fill by rows, set the byrow option to TRUE.

matrix(1:4, ncol = 2, byrow = TRUE)
     [,1] [,2]
[1,]    1    2
[2,]    3    4

In general, creating matrices by row makes the code and the matrix look similar:

matrix(c(3, 5, 
         2, 3),
       nrow = 2,
       byrow = TRUE)
     [,1] [,2]
[1,]    3    5
[2,]    2    3

To achieve the same matrix without the byrow option set to TRUE is possible, but the code will be the same order as the matrix:

matrix(c(3, 2, 
         5, 3),
       nrow = 2)
     [,1] [,2]
[1,]    3    5
[2,]    2    3
You Try

Make vector A into a 2 by 2 matrix like so:

\mathbf{A}=\begin{bmatrix} 2&3\\ 5&7 \end{bmatrix}

Suggested Solution
# Using the matrix function setting byrow = TRUE
A <- matrix(c(2, 3,
              5, 7),
            nrow = 2,
            byrow = TRUE)

5.1 Appending Matrices

\color{RoyalBlue}{\mathbf{A}}=\begin{bmatrix} \color{RoyalBlue}{1} & \color{RoyalBlue}{2} & \color{RoyalBlue}{3} & \color{RoyalBlue}{4} \\ \color{RoyalBlue}{5} & \color{RoyalBlue}{6} & \color{RoyalBlue}{7} & \color{RoyalBlue}{8} \\ \color{RoyalBlue}{9} & \color{RoyalBlue}{10} & \color{RoyalBlue}{11} & \color{RoyalBlue}{12} \end{bmatrix}, \color{Firebrick}{\mathbf{B}}=\begin{bmatrix} \color{Firebrick}{13} & \color{Firebrick}{14} & \color{Firebrick}{15} & \color{Firebrick}{16} \\ \color{Firebrick}{17} & \color{Firebrick}{18} & \color{Firebrick}{19} & \color{Firebrick}{20} \end{bmatrix}

The equation below means, “Make a new matrix called C by appending B to the bottom of A.”

\mathbf{C}=\begin{bmatrix} \color{RoyalBlue}{\mathbf{A}} \\ \color{FireBrick}{\mathbf{B}} \end{bmatrix}= \begin{bmatrix} \color{RoyalBlue}{1} & \color{RoyalBlue}{2} & \color{RoyalBlue}{3} & \color{RoyalBlue}{4} \\ \color{RoyalBlue}{5} & \color{RoyalBlue}{6} & \color{RoyalBlue}{7} & \color{RoyalBlue}{8} \\ \color{RoyalBlue}{9} & \color{RoyalBlue}{10} & \color{RoyalBlue}{11} & \color{RoyalBlue}{12}\\ \color{Firebrick}{13} & \color{Firebrick}{14} & \color{Firebrick}{15} & \color{Firebrick}{16} \\ \color{Firebrick}{17} & \color{Firebrick}{18} & \color{Firebrick}{19} & \color{Firebrick}{20} \end{bmatrix}

In R, adding new rows to a matrix is done with the rbind function (Think “row bind”). To append rows, matrices must have the same number of columns to be compatible.

A <- matrix(1:12, nrow = 3, byrow = TRUE)
B <- matrix(13:20, nrow = 2, byrow = TRUE)
C <- rbind(A,B)
C
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8
[3,]    9   10   11   12
[4,]   13   14   15   16
[5,]   17   18   19   20

The cbind function (Think “column bind”) works the same way but it appends columns to the right of a matrix. Matrices must have the same number of rows to be compatible.

A <- matrix(1:4, nrow = 2)
B <- matrix(5:8, nrow = 2)
C <- cbind(A,B)
C
     [,1] [,2] [,3] [,4]
[1,]    1    3    5    7
[2,]    2    4    6    8
You Try

Make a 2 by 2 matrix A:

A=\begin{bmatrix} 11&13\\ 17&19 \end{bmatrix}

Make a 2 by 2 matrix B:

B=\begin{bmatrix} 11&13\\ 17&19 \end{bmatrix}

Append A and B with rbind to make a 4 by 2 matrix like so:

\begin{bmatrix} 2&3\\ 5&7\\ 11&13\\ 17&19 \end{bmatrix}

Suggested Solution
A <- matrix(c(2, 5, 3, 7), nrow = 2)
B <- matrix(c(11,17,13,19), nrow = 2)
rbind(A, B)
     [,1] [,2]
[1,]    2    3
[2,]    5    7
[3,]   11   13
[4,]   17   19

Now use cbind to make a 2 by 4 matrix:

\begin{bmatrix} 2&3&11&13\\ 5&7&17&19 \end{bmatrix}

Suggested Solution
cbind(A, B)
     [,1] [,2] [,3] [,4]
[1,]    2    3   11   13
[2,]    5    7   17   19

5.2 Selecting parts of a matrix

Let’s make this matrix:

\mathbf{A} = \begin{bmatrix} 1&2&3&4\\ 5&6&7&8\\ 9&10&11&12 \end{bmatrix}

A <- matrix(1:12, nrow = 3, byrow = TRUE)
A
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8
[3,]    9   10   11   12

5.2.1 Select a single element of a matrix

To select a single element of a matrix, specify the row and column in brackets after the matrix. For example, the element \mathbf{A}_{3,2} (i.e., the 3rd row and 2nd column of \mathbf{A}) is

A[3,2]
[1] 10
You Try

Select the element in row 2, column 3

Suggested Solution
A[2,3]
[1] 7

5.2.2 Select a matrix row

Leaving one of the slots in the bracket empty means that you want all of the elements in that row or column.

\mathbf{A}_{1\bullet} is the 1st row of \mathbf{A}.

A[1, ]
[1] 1 2 3 4

5.2.3 Select a matrix column

\mathbf{A}_{\bullet 3} is the 3rd column of \mathbf{A}.

A[, 3]
[1]  3  7 11

By default, whenever a single row, column, or element is returned from a matrix, R drops the row and column dimensions. If you wish to preserve the result in matrix form, set drop to FALSE:

A[, 3, drop = FALSE]
     [,1]
[1,]    3
[2,]    7
[3,]   11

Select column 1 of A.

Suggested Solution
A[, 1]
[1] 1 5 9

5.2.4 Select several columns or rows

A vector of integers will select whichever rows or columns you wish. Here are the 2nd and 3rd rows:

A[2:3, ]
     [,1] [,2] [,3] [,4]
[1,]    5    6    7    8
[2,]    9   10   11   12

Here are the 1st and 4th columns:

A[, c(1, 4)]
     [,1] [,2]
[1,]    1    4
[2,]    5    8
[3,]    9   12

Select columns 1 and 3 of A.

Suggested Solution
A[, c(1, 3)]
     [,1] [,2]
[1,]    1    3
[2,]    5    7
[3,]    9   11

5.2.5 Selecting with Boolean vectors

Here is the first two rows of \mathbf{A}:

A[c(TRUE,TRUE,FALSE),]
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8

This seems like a strange way to do this but it is actually quite powerful. Any vector of TRUE and FALSE values can be used to select things. For example, select a column only if its first value is greater than 2:

s <- A[1,] > 2 # Creates a vector that tests whether the first row elements are greater than 2
A[,s] # Select only the columns whose first value is greater than 2
     [,1] [,2]
[1,]    3    4
[2,]    7    8
[3,]   11   12

Use a Boolean vector to select columns that begin with 2. The operator for “is equal to” is ==.

Suggested Solution
s <- A[1,] == 2 
# When only one column or row is selected, R returns a vector
A[,s]
[1]  2  6 10
# To force R to return a matrix, set drop = FALSE
A[,s, drop = FALSE]
     [,1]
[1,]    2
[2,]    6
[3,]   10

5.2.6 Selecting with name vectors

We can give row and column names to a matrix like so:

rownames(A) <- c("Gold","Silver","Bronze")
colnames(A) <- c("Vault","Uneven Bars","Balance Beam","Floor")
A
       Vault Uneven Bars Balance Beam Floor
Gold       1           2            3     4
Silver     5           6            7     8
Bronze     9          10           11    12

Now we can select rows and columns by names:

A[c("Gold","Bronze"),]
       Vault Uneven Bars Balance Beam Floor
Gold       1           2            3     4
Bronze     9          10           11    12

Use the column names to select the Uneven Bars column

Suggested Solution
A[,"Uneven Bars"]
  Gold Silver Bronze 
     2      6     10 
# or to force returning a matrix
A[,"Uneven Bars", drop = FALSE]
       Uneven Bars
Gold             2
Silver           6
Bronze          10

Select the intersection of Silver and Floor

Suggested Solution
A["Silver", "Floor"]
[1] 8
# or
A["Silver", "Floor", drop = FALSE]
       Floor
Silver     8

5.3 Replace portions of a matrix

Any portion of a matrix can be replaced with new values. For example, this will replace the first row with zeros:

A[1, ] <- c(0, 0, 0, 0)
A
       Vault Uneven Bars Balance Beam Floor
Gold       0           0            0     0
Silver     5           6            7     8
Bronze     9          10           11    12

This can be done by column or row name as well

A["Gold", ] <- c(0, 0, 0, 0)
A
       Vault Uneven Bars Balance Beam Floor
Gold       0           0            0     0
Silver     5           6            7     8
Bronze     9          10           11    12

Replace the Vault column of \mathbf{A} with a vector of (10,20,30)

Suggested Solution
A[, "Vault"] <- c(10, 20, 30)
A
       Vault Uneven Bars Balance Beam Floor
Gold      10           0            0     0
Silver    20           6            7     8
Bronze    30          10           11    12

5.4 Transposing matrices

To transpose a matrix is to flip its rows into columns.

To transpose a matrix is to write its rows as columns and its columns as rows.

\mathbf{A}' is matrix \mathbf{A} transposed.

If

\mathbf{A}=\begin{bmatrix} 1&2&3\\ 4&5&6 \end{bmatrix}

Then

\mathbf{A}'=\begin{bmatrix} 1&4\\ 2&5\\ 3&6 \end{bmatrix}

5.4.1 Transposing in R

In R the t function transposes matrices.

A <- matrix(1:6, nrow = 2, byrow = TRUE)
A
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
Aprime <- t(A)
Aprime
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
  1. Make a 2 \times 5 matrix A of even numbers up to 20.
  2. Transpose A, assigning it to a variable called Aprime.
  3. Replace the last row (row 5) of Aprime with zeroes.
Suggested Solution
A <- matrix(seq(2, 20, 2), nrow = 2)
A
     [,1] [,2] [,3] [,4] [,5]
[1,]    2    6   10   14   18
[2,]    4    8   12   16   20
Aprime <- t(A)
Aprime
     [,1] [,2]
[1,]    2    4
[2,]    6    8
[3,]   10   12
[4,]   14   16
[5,]   18   20
Aprime[5, ] <- c(0, 0)
Aprime
     [,1] [,2]
[1,]    2    4
[2,]    6    8
[3,]   10   12
[4,]   14   16
[5,]    0    0

5.5 Square matrices

In a square matrix, the number of rows is equal to the number of columns.

5.6 Symmetric matrices

A symmetric matrix is a square matrix that is equal to its transpose.

\mathbf{A}=\mathbf{A}'

This means that for all elements, a_{ij}=a_{ji}.

Here is an example of a symmetric matrix:

\begin{bmatrix} \color{green}a & \color{Firebrick}b & \color{RoyalBlue}c\\ \color{Firebrick}b & \color{gold}d & \color{DarkOrchid}e\\ \color{RoyalBlue}c & \color{DarkOrchid}e & \color{orange}f \end{bmatrix}

To verify that a matrix is symmetric in R:

all(A == t(A))
# Or use a dedicated function
isSymmetric(A)

Correlation matrices and covariance matrices are always symmetric.

5.7 Diagonal matrices

A diagonal matrix is a square matrix consisting of zeroes everywhere except the diagonal. For example,

\mathbf{A} = \begin{bmatrix} a & 0 & 0\\ 0 & b & 0\\ 0 & 0 & c \end{bmatrix}

To create a diagonal matrix, specify the diagonal vector and then insert it into the diag function like so:

a <- 1:4
A <- diag(a)
A
     [,1] [,2] [,3] [,4]
[1,]    1    0    0    0
[2,]    0    2    0    0
[3,]    0    0    3    0
[4,]    0    0    0    4

As we will see later, the diag function actually has several different purposes:

  1. It creates a diagonal matrix \mathbf{A} from a vector \vec{a}.
    A <- diag(a)
  2. It extracts a diagonal vector \vec{a} from a matrix \mathbf{A}.
    a <- diag(A)
  3. It creates an identity matrix \mathbf{I} from a positive integer n.
    I <- diag(n)
  4. It replaces the diagonal of matrix \mathbf{A} with a new vector \vec{b}.
    diag(A) <- b