Open the Work Along file to find data and questions to accompany the material.

Creating matrices

You’re all familiar with what a matrix is mathematically. It is a 2-dimensional array of symbols – like a 2-dimensional vector. In fact, that’s how R implements matrices; they are vectors organized into an array with a multidimensional index.

Matrices are instantiated with the matrix function, in which we specify the vector of entries and the numbers of rows and columns.

v1 <- 1:9 # a vector of length 9 = 3 x 3
m1 <- matrix(v1, nrow=3, ncol=3)
m1
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9

You see it filled in the entries going down the column. If you try to form a matrix with a vector that’s too short, R pads it with NA’s.

Matrices of characters or logicals can also be created.

m2 <- matrix(letters[1:8], nrow=2, ncol=4)
m2
##      [,1] [,2] [,3] [,4]
## [1,] "a"  "c"  "e"  "g" 
## [2,] "b"  "d"  "f"  "h"

But if you try to mix numeric and character entries, the numbers are converted to characters, just like with vectors.

Names and dimensions

R has functions that return dimnesions just like length works for vectors.

nrow(m2)
## [1] 2
ncol(m2)
## [1] 4
dim(m2)
## [1] 2 4

Just as a vector can have names associated to the entries, a matrix can have names for columns and rows.

dim(m1)
## [1] 3 3
colnames(m1) <- c("C1", "C2", "C3")
rownames(m1) <- c("R1", "R2", "R3")
m1
##    C1 C2 C3
## R1  1  4  7
## R2  2  5  8
## R3  3  6  9

Identifying entries by rows and columns

There are no surprises in how a cell in a matrix is identified.

m2
##      [,1] [,2] [,3] [,4]
## [1,] "a"  "c"  "e"  "g" 
## [2,] "b"  "d"  "f"  "h"
m2[1, 2] # row 1, column 2
## [1] "c"

You can also use row and column names to pin down an entry.

m1["R2", "C3"]
## [1] 8

Specifying ranges of columns and rows will give a submatrix.

m1[1:2, 2:3] # The row and column names ride along
##    C2 C3
## R1  4  7
## R2  5  8

Leaving one slot empty fetches all rows or columns.

m2[ ,1:3]
##      [,1] [,2] [,3]
## [1,] "a"  "c"  "e" 
## [2,] "b"  "d"  "f"

Note that if you specify a single row or column, R drops the matrix structure and returns a vector.

v2 <- m1[1,]
v2
## C1 C2 C3 
##  1  4  7
class(v2)
## [1] "integer"
dim(v2)
## NULL
v22 <- as.matrix(m1[1,])
v22
##    [,1]
## C1    1
## C2    4
## C3    7
d <- matrix(NA, nrow=3, ncol=3)
d
##      [,1] [,2] [,3]
## [1,]   NA   NA   NA
## [2,]   NA   NA   NA
## [3,]   NA   NA   NA
d[1, ] <- c(1,2,3)
d
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]   NA   NA   NA
## [3,]   NA   NA   NA

Conditionals, logicals and subsetting

Equalities and inequalities of matrices return logical matrices of the same dimensions. Think of how the coniditional works on the underlying vector.

m1 > 4
##       C1    C2   C3
## R1 FALSE FALSE TRUE
## R2 FALSE  TRUE TRUE
## R3 FALSE  TRUE TRUE

Subsetting with a logical vector in the row or column slot selects the TRUE rows or columns. You can also subset with logical matrices, although it isn’t used much.

m1[m1 >4]
## [1] 5 6 7 8 9

Here, we just got the vector. This may not be very useful but it may be for assignment.

m1[m1 > 4] <- 0
m1
##    C1 C2 C3
## R1  1  4  0
## R2  2  0  0
## R3  3  0  0

Operations

Arithmetic operations with matrices are computed component-wise, just like vectors. This can lead to surprising behavior.

m1
##    C1 C2 C3
## R1  1  4  0
## R2  2  0  0
## R3  3  0  0
2*m1
##    C1 C2 C3
## R1  2  8  0
## R2  4  0  0
## R3  6  0  0
w <- c(-1, -2, -3)
m1 * w
##    C1 C2 C3
## R1 -1 -4  0
## R2 -4  0  0
## R3 -9  0  0

This multipled each column by w, entry by entry.

To perform matrix multiplication, use the %*% operator. You may need to transpose a matrix or extract the diagonal. The R functions for those are t and diag. R also has functions for doing linear algebra, like singular value decomposition.

m1 %*% w
##    [,1]
## R1   -9
## R2   -2
## R3   -3
m1
##    C1 C2 C3
## R1  1  4  0
## R2  2  0  0
## R3  3  0  0
t(m1)
##    R1 R2 R3
## C1  1  2  3
## C2  4  0  0
## C3  0  0  0
diag(m1)
## [1] 1 0 0

Adding new rows and columns

The functions cbind and rbind flexibly add columns and rows, and even concatenates matrices.

m1
##    C1 C2 C3
## R1  1  4  0
## R2  2  0  0
## R3  3  0  0
mm1 <- cbind(m1, c(-1, -1, -1))
mm1
##    C1 C2 C3   
## R1  1  4  0 -1
## R2  2  0  0 -1
## R3  3  0  0 -1
mm2 <- cbind(m1, matrix(rep(0, times = 9), nrow=3, ncol=3))
mm2
##    C1 C2 C3      
## R1  1  4  0 0 0 0
## R2  2  0  0 0 0 0
## R3  3  0  0 0 0 0
colnames(mm2)
## [1] "C1" "C2" "C3" ""   ""   ""

No surprises with rbind.

mm3 <- rbind(m1, matrix(rep(0, times = 9), nrow=3, ncol=3))
mm3
##    C1 C2 C3
## R1  1  4  0
## R2  2  0  0
## R3  3  0  0
##     0  0  0
##     0  0  0
##     0  0  0