# example 1
m1 <- matrix(1:6, nrow = 2, ncol = 3)
m1 [,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
Stat 133
matrix()cbind() and rbind()mat[row,col]matrix()An R matrix provides a rectangular data object: to handle data in a two-dimensional array.
The function matrix() is the primary function to create matrices in R. matrix() takes—ideally—a vector x as input, and returns a matrix arranging the elements in x according to the specified number of rows nrow and columns ncol. For example:
# example 1
m1 <- matrix(1:6, nrow = 2, ncol = 3)
m1 [,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
# example 2
m2 <- matrix(1:6, nrow = 3, ncol = 2)
m2 [,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
A few important aspects about R matrices:
R internally stores matrices as vectors.
Which means that matrices are also atomic (i.e. all the elements in a matrix must be of the same data type).
Matrices in R are stored column-major (i.e. by columns).
This is like Fortran, Matlab, and Julia, but not like C or Python (e.g. numpy)
byrowThe matrix() function comes with the byrow argument that allows you to arrange values by-row instead of by-column; here’s an example:
# example 2
m3 <- matrix(1:6, nrow = 2, ncol = 3, byrow = TRUE)
m3 [,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
Keep in mind that m3 is still stored column-major. You can confirm this by asking R to vectorize m3
as.vector(m3)[1] 1 4 2 5 3 6
matrix() exampleHow do you create the following matrix?
[,1] [,2]
[1,] "Harry" "Potter"
[2,] "Ron" "Weasley"
[3,] "Hermione" "Granger"
Here’s one way to create the preceding matrix:
# vector of names
hp <- c("Harry", "Ron", "Hermione",
"Potter", "Weasley", "Granger")
# matrix filled up by rows
matrix(hp, nrow = 3) [,1] [,2]
[1,] "Harry" "Potter"
[2,] "Ron" "Weasley"
[3,] "Hermione" "Granger"
Here’s another way to create the same matrix:
# vector of names
hp <- c("Harry", "Potter", "Ron", "Weasley",
"Hermione", "Granger")
# matrix filled up by rows
matrix(hp, nrow = 3, byrow = TRUE) [,1] [,2]
[1,] "Harry" "Potter"
[2,] "Ron" "Weasley"
[3,] "Hermione" "Granger"
Matrices have:
length(): number of cells
typeof(): data type (recall that matrices are atomic)
dim(): dimensions; number of rows and columns
nrow(): number of rowsncol(): number of columnsWe also have functions that let you set/get the names for either the rows or the columns (or both) of a matrix:
rownames()
colnames()
dimnames()
# rownames
set.seed(123)
A <- matrix(runif(12), nrow = 3, ncol = 4)
rownames(A) <- paste0("row", 1:nrow(A))
A [,1] [,2] [,3] [,4]
row1 0.2875775 0.8830174 0.5281055 0.4566147
row2 0.7883051 0.9404673 0.8924190 0.9568333
row3 0.4089769 0.0455565 0.5514350 0.4533342
rownames(A)[1] "row1" "row2" "row3"
set.seed(123)
B <- matrix(runif(12), nrow = 3, ncol = 4)
colnames(B) <- paste0("col", 1:ncol(B))
B col1 col2 col3 col4
[1,] 0.2875775 0.8830174 0.5281055 0.4566147
[2,] 0.7883051 0.9404673 0.8924190 0.9568333
[3,] 0.4089769 0.0455565 0.5514350 0.4533342
colnames(B)[1] "col1" "col2" "col3" "col4"
set.seed(123)
C <- matrix(runif(12), nrow = 3, ncol = 4)
rownames(C) <- paste0("row", 1:nrow(C))
colnames(C) <- paste0("col", 1:ncol(C))
C col1 col2 col3 col4
row1 0.2875775 0.8830174 0.5281055 0.4566147
row2 0.7883051 0.9404673 0.8924190 0.9568333
row3 0.4089769 0.0455565 0.5514350 0.4533342
dimnames(C)[[1]]
[1] "row1" "row2" "row3"
[[2]]
[1] "col1" "col2" "col3" "col4"
Recycling rules also apply to matrices, for example:
x <- letters[1:4]
X <- matrix(x, nrow = 4, ncol = 3)
X [,1] [,2] [,3]
[1,] "a" "a" "a"
[2,] "b" "b" "b"
[3,] "c" "c" "c"
[4,] "d" "d" "d"
Here are more recycling examples:
# "empty" matrices
mat_chr <- matrix("", nrow = 4, ncol = 3)
mat_num <- matrix(0, nrow = 4, ncol = 3)
mat_lgl <- matrix(NA, nrow = 4, ncol = 3)Another way to form matrices is by joining or binding either vectors or matrices by rows—with rbind()—or by columns—with cbind(). For example:
a <- c(2, 4, 6)
b <- c(1, 3, 5)# column bind
cbind(a, b) a b
[1,] 2 1
[2,] 4 3
[3,] 6 5
cbind(m3, b)Warning in cbind(m3, b): number of rows of result is not a multiple of vector
length (arg 2)
b
[1,] 1 2 3 1
[2,] 4 5 6 3
# row bind
rbind(b, a) [,1] [,2] [,3]
b 1 3 5
a 2 4 6
rbind(m2, a)Warning in rbind(m2, a): number of columns of result is not a multiple of
vector length (arg 2)
[,1] [,2]
1 4
2 5
3 6
a 2 4
To do subsetting (i.e. subscripting, indexing) on a matrix, you use bracket notation, passing two indexing vectors separated by a comma: the first one for indexing rows, the second one for indexing columns.
# cell in row 1, column 3 of matrix m1
m1[1,3][1] 5
# 2nd column of matrix m2
m2[ ,2][1] 4 5 6
# 1st row of matrix m3
m3[1, ][1] 1 2 3
Keep in mind that you can also specify a single indexing vector inside brackets, without any commas:
# 2nd element
m1[2][1] 2
And you can also specify double brackets:
# 2nd element
m1[[2]][1] 2
Keep in mind that the two preceding subsetting examples are not commonly used among R users. While they are perfectly valid commands, we prefer to explicitly denote the comma , while subsetting matrices.
In case you are curious about what kind of common matrix operators and linear algebra functions are available in R:
| Operator | Description | Example |
|---|---|---|
+ |
addition | A + B |
- |
subtraction | A - B |
* |
elementwise product | A * B |
%*% |
matrix product | A %*% B |
t() |
transpose | t(A) |
det() |
determinant | det(A) |
diag() |
extract diagonal | diag(A) |
solve() |
inverse | solve(A) |
Make sure the dimensions of matrices are conformable when using an operator or some calculation on them.
| Function | Description |
|---|---|
upper.tri() |
upper triangular part of a matrix |
lower.tri() |
upper triangular part of a matrix |
eigen() |
eigenvalue decomp. |
svd() |
singular value decomp. |
lu() |
Triangular decomposition |
qr() |
QR decomposition |
chol() |
Cholesky decomposition |