What is a Matrix?
A matrix is a collection of elements, all the same type, arranged in a two-dimensional layout.
In a nutshell, a matrix is just a vector that has two dimensions.
When using R, you will frequently encounter the four basic matrix types viz. logical, character, integer and double (often called numeric).
Create a Matrix
You can create a matrix using the matrix()
function and specifying the data and the number of rows and columns to make the matrix.
# Create a numeric matrix
m <- matrix(1:6, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
Matrix can contain character values as well.
# Create a character matrix
letters <- c("a","b","c","d","e","f")
m <- matrix(letters, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,] "a" "c" "e"
[2,] "b" "d" "f"
You don’t have to specify both ncol and nrow. If you specify one, R will know automatically what the other needs to be.
m <- matrix(1:6, nrow=2)
m
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
By default, the matrix is filled column-by-column. By setting byrow=TRUE
you can fill the matrix row-by-row.
m <- matrix(1:6, nrow=2, ncol=3, byrow=TRUE)
m
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
Combine Vectors into a Matrix
You can also create a matrix using the cbind()
and rbind()
functions. However, keep in mind that the vectors that are being binded must be of equal length and same type.
v1 <- c(1, 2, 3)
v2 <- c(4, 5, 6)
v3 <- c(7, 8, 9)
rbind(v1, v2, v3)
[,1] [,2] [,3]
v1 1 2 3
v2 4 5 6
v3 7 8 9
The cbind()
function does something similar. It binds the vectors as columns of a matrix.
v1 <- c(1, 2, 3)
v2 <- c(4, 5, 6)
v3 <- c(7, 8, 9)
cbind(v1, v2, v3)
v1 v2 v3
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
Change Matrix Dimension
By using the dim()
function you can get the dimension of the matrix without looking at the structure.
# Print the dimension of a matrix
m <- matrix(1:6, nrow=2, ncol=3)
dim(m)
[1] 2 3
The dim()
function can also be used to set the dimension of the matrix.
# Change the dimension of a matrix
# define a 2x3 matrix
m <- matrix(1:6, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
# make it 3x2
dim(m) <- c(3,2)
m
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
# make it 1x6
dim(m) <- c(1,6)
m
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
Naming Matrix Rows and Columns
R lets you assign descriptive names to the rows and columns of a matrix. It is useful for subsetting and printing the matrix.
You can do this by assigning two element list containing row and column names to the dimnames attribute.
# Assign names to the rows and columns
m <- matrix(1:6, nrow=2, ncol=3)
dimnames(m) <- list(c("r1","r2"), c("c1","c2","c3"))
m
c1 c2 c3
r1 1 3 5
r2 2 4 6
You can even name the rows and columns while creating a matrix by passing dimnames argument.
# Naming rows and columns while matrix creation
m <- matrix(1:6, nrow=2, ncol=3, dimnames=list(c("r1","r2"), c("c1","c2","c3")))
m
c1 c2 c3
r1 1 3 5
r2 2 4 6
By using the rownames()
and colnames()
function you can assign row names and column names separately.
# Assign names to the rows and columns separately
m <- matrix(1:6, nrow=2, ncol=3)
rownames(m) <- c("r1","r2")
colnames(m) <- c("c1","c2","c3")
m
c1 c2 c3
r1 1 3 5
r2 2 4 6
You can use the same dimnames()
, colnames()
and rownames()
functions to print column names and row names.
# print column names
colnames(m)
[1] "c1" "c2" "c3"
# print row names
rownames(m)
[1] "r1" "r2"
# print both
dimnames(m)
[[1]]
[1] "r1" "r2"
[[2]]
[1] "c1" "c2" "c3"
Subsetting Matrices
In R, subsetting elements from matrices is much like subsetting elements from vectors.
The only difference is that you now have to specify both the row and the column position, in the order of [row, column]
.
Subsetting by Positive Integer
Subsetting with positive integers returns the elements at the specified positions.
m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
# subset for 2nd row
m[2,]
[1] 2 5 8
# subset for 3rd column
m[,3]
[1] 7 8 9
# select single element
m[2,3]
[1] 8
# subset for row 1 and 2 but keep all columns
m[1:2,]
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
# subset for both rows and columns
m[1:2,2:3]
[,1] [,2]
[1,] 4 7
[2,] 5 8
# use a vector to subset
m[1:2,c(1, 3)]
[,1] [,2]
[1,] 1 7
[2,] 2 8
When you subset for a single row or a column, the result will always be a vector. To avoid this you can set the drop argument to FALSE.
m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
# simplifies the output to a vector
m[, 2]
[1] 4 5 6
class(m[, 2])
[1] "integer"
# preserves output as a matrix
m[, 2, drop = FALSE]
[,1]
[1,] 4
[2,] 5
[3,] 6
class(m[, 2, drop = FALSE])
[1] "matrix"
Subsetting by Negative Integer
Subsetting with negative integers will omit the elements at the specified positions.
m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
# omit 2nd row
m[-2,]
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 3 6 9
# omit 3rd column
m[,-3]
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
# omit 2nd row and 3rd column
m[-2,-3]
[,1] [,2]
[1,] 1 4
[2,] 3 6
Subsetting by Logical Values
Subsetting with logical values will return the elements where the corresponding logical value is TRUE.
m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
# select elements where corresponding logical value is TRUE
m[c(TRUE,FALSE,TRUE),c(TRUE,TRUE,FALSE)]
[,1] [,2]
[1,] 1 4
[2,] 3 6
# select elements greater than 5
m[m > 5]
[1] 6 7 8 9
# select even elements
m[m %% 2 == 0]
[1] 2 4 6 8
Subsetting by Names
Subsetting with names will return the elements having the matching names.
m <- matrix(1:9, nrow=3, ncol=3)
dimnames(m) <- list(c("r1","r2","r3"), c("c1","c2","c3"))
# subset for 2nd row
m["r2",]
c1 c2 c3
2 5 8
# subset for 3rd column
m[,"c3"]
r1 r2 r3
7 8 9
# subset for 1st and 3rd row but keep all columns
m[c("r1","r3"),]
c1 c2 c3
r1 1 4 7
r3 3 6 9
# select single element
m["r2","c3"]
[1] 8
Add New Rows and Columns to Matrix
You can use the cbind()
and rbind()
functions for adding new rows and columns to the matrix as well. However, keep in mind that the vectors that are being added must be of equal length and same type.
m <- matrix(1:6, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
# add new column
cbind(m, c(7,8))
[,1] [,2] [,3] [,4]
[1,] 1 3 5 7
[2,] 2 4 6 8
# add new row
rbind(m, c(10,20,30))
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
[3,] 10 20 30
Modify Matrix Elements
Modifying a matrix element is pretty straightforward. Access the element using []
operator and simply assign a new value.
m <- matrix(1:6, nrow=2, ncol=3)
# moidfy single element
m[1,2] <- 99
m
[,1] [,2] [,3]
[1,] 1 99 5
[2,] 2 4 6
# modify 2nd row
m[2,] <- c(10,20,30)
m
[,1] [,2] [,3]
[1,] 1 99 5
[2,] 10 20 30
# modify elements less than 5
m[m > 5] <- 0
m
[,1] [,2] [,3]
[1,] 1 0 5
[2,] 0 0 0
Matrix Operations
The most powerful feature of R is the ease of dealing with matrix operations. Because much of statistics depend on matrix operations, R perform them in an easy and optimized way:
- Matrix transpose
- Creating an identity matrix
- Scalar multiple of a matrix
- Matrix addition and subtraction
- Matrix multiplication
- Matrix inversion
Matrix Transpose
The transpose of a matrix is simply a flipped version of the original matrix obtained by switching rows with columns. To transpose a matrix, use t()
function.
m <- matrix(1:6, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
t(m)
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
Creating an Identity Matrix
You can create an identity matrix using the diag()
function. Its behavior depends on what argument you pass.
If you pass a single positive integer, then diag()
will create an identity matrix of that dimension.
# Create a 3x3 identity matrix
diag(3)
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
If you pass a matrix, diag()
will return the diagonal elements of the matrix.
# Return diagonal elements of the matrix
m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
diag(m)
[1] 1 5 9
Scalar Multiple of a Matrix
When you multiply a matrix by a scalar value (a single number), every individual element is multiplied by that value.
# Multiply each matrix element by 10
m <- matrix(1:6, nrow=2, ncol=3)
m * 10
[,1] [,2] [,3]
[1,] 10 30 50
[2,] 20 40 60
Matrix Addition and Subtraction
R performs addition or subtraction of two matrices of equal size in an element-wise manner. Meaning, corresponding elements are added or subtracted from one another, depending on the operation.
m1 <- matrix(1:6, nrow=2, ncol=3)
m1
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
m2 <- matrix(-6:-1, nrow=2, ncol=3)
m2
[,1] [,2] [,3]
[1,] -6 -4 -2
[2,] -5 -3 -1
# addition
m1 + m2
[,1] [,2] [,3]
[1,] -5 -1 3
[2,] -3 1 5
# subtraction
m1 - m2
[,1] [,2] [,3]
[1,] 7 7 7
[2,] 7 7 7
Matrix Multiplication
Unlike scalar multiplication, matrix multiplication is not a simple element-by-element calculation, and the standard *
operator cannot be used. Instead, you must use R’s matrix product operator %*%
.
m1 <- matrix(1:6, nrow=2, ncol=3)
m1
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
m2 <- matrix(1:6, nrow=3, ncol=2)
m2
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
# multiplication
m1 %*% m2
[,1] [,2]
[1,] 22 49
[2,] 28 64
Matrix Inversion
The inverse of a matrix can be calculated by using the solve()
function.
m <- matrix(1:4, nrow=2, ncol=2)
m
[,1] [,2]
[1,] 1 3
[2,] 2 4
solve(m)
[,1] [,2]
[1,] -2 1.5
[2,] 1 -0.5
Matrix Length
You can find the total number of values in a matrix using the length()
function.
m <- matrix(1:6, nrow=2, ncol=3)
length(m)
[1] 6