In R, matrix is a vector with two additional attributes, the number of rows and the number of columns. Since vectors are the building blocks of matrices, like vectors, matrices are also constrained to single data type. In this article, we will create, name, subset the matrices. We will also perform some arithmetic operations on matrices.
Creating a Matrix
We can use matrix( ) function to create a matrix. We have to supply vector of values and number of rows and columns matrix should have.
temp_matrix <- matrix(c(1:6),nrow=2,ncol=3)
temp_matrix
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
If we specify the vector of values and one of the dimensions, the other one will be calculated automatically from length of data and other dimension.
temp_matrix <- matrix(c(1:6),nrow=3)
temp_matrix
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
Since length of data is 6, and number of rows specified as 3, the number of columns is calculated as 2 (length = columns ∗ rows)
By default, matrices are filled column wise, meaning that the entries can be thought of as starting in the upper-left corner and running down the columns. However, if we prefer to construct it row-wise, we can send the byrow = TRUE parameter.
temp_matrix <- matrix(c(1:6),nrow=3,byrow = TRUE)
temp_matrix
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
Please note, position of matrix elements is changed, since the matrix is filled by rows.
We can also create empty matrix, by specifying number of rows and columns without passing any actual data.
null_matrix <- matrix(nrow=3,ncol=2)
null_matrix
[,1] [,2]
[1,] NA NA
[2,] NA NA
[3,] NA NA
If there are too few elements in data, then the elements in data is recycled.
temp_matrix1 <- matrix(c(1:6),nrow = 2, ncol=4)
temp_matrix1
[,1] [,2] [,3] [,4]
[1,] 1 3 5 1
[2,] 2 4 6 2
In the previous example, the matrix data is recycled to fill in fourth column. Conversely, if product of rows and columns specified is less than length of a data, the additional elements in a matrix data are trimmed down.
temp_matrix1 <- matrix(c(1:6),nrow = 2, ncol=2)
temp_matrix1
[,1] [,2]
[1,] 1 3
[2,] 2 4
Matrices can be created by column-binding or row-binding with the cbind( ) and rbind( ) functions.
x <- 1:3
y <- 10:12
cbind(x, y) # builds matrix by combining columns
x y
[1,] 1 10
[2,] 2 11
[3,] 3 12
rbind(x,y) # builds matrix by combining rows
[,1] [,2] [,3]
x 1 2 3
y 10 11 12
Naming Rows and Columns
By default, creating a matrix does not automatically give names to its rows and columns. Sometimes, it is useful and straightforward to do so when different rows and columns have different meanings. Let’s create a sales table for two products sold in two different geographies.
sale_data <- matrix(c(100,150,200,250),nrow=2)
rownames(sale_data) <- c("North", "South")
colnames(sale_data) <- c("Product A", "Product B")
sale_data
Product A Product B
North 100 200
South 150 250
Subsetting a Matrix
Matrices can be subsetted in the usual way with (i, j) type indices. Here, we create simple 2 X 3 matrix.
matrix_sub <- matrix(c(1:6),nrow=2,ncol=3)
matrix_sub
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
Since in this case, we have two dimensions to work with, we must separate the selection for rows and columns by using a comma (,) between them (row selection goes first), and R will return their intersection.
matrix_sub[1,2] # select element from first row of second column
[1] 3
matrix_sub[c(1:2),3] #select elements from first two rows of third column
[1] 5 6
We can also use logical vectors for selection. For e.g. [c(TRUE, FALSE), c(FALSE, TRUE, TRUE)] tells R to select first row while filtering out the second one, and from that row, select second and third columns.
matrix_sub[c(TRUE,FALSE),c(FALSE,TRUE,TRUE)]
[1] 3 5
matrix_sub[1,c(2,3)] # An equivalent selection
[1] 3 5
If one dimension is left blank, all the values in that dimension will be selected:
matrix_sub[1, ] # select all columns across first row
[1] 1 3 5
matrix_sub[ ,1] # select all rows in first column
[1] 1 2
matrix_sub[c(1,2), ] # select all columns across rows 1 and 2
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
Negative numbers exclude the positions in subsetting the matrix.
matrix_sub[-1, ] # exclude first row
[1] 2 4 6
matrix_sub[, -1] # exclude first column
[,1] [,2]
[1,] 3 5
[2,] 4 6
Matrix Operator
All arithmetic operators for vectors also work with matrices as if they were vectors. These operators perform calculations element-wise, except for matrix-only operators, such as matrix product.
matrix1 <- matrix(c(10:15),nrow=2)
matrix1
[,1] [,2] [,3]
[1,] 10 12 14
[2,] 11 13 15
matrix2 <- matrix(c(20:25),nrow=2)
matrix2
[,1] [,2] [,3]
[1,] 20 22 24
[2,] 21 23 25
Some arithmetic operators on matrix are as below:
matrix1 + matrix2 # addition
[,1] [,2] [,3]
[1,] 30 34 38
[2,] 32 36 40
matrix1/matrix2 # division
[,1] [,2] [,3]
[1,] 0.5000000 0.5454545 0.5833333
[2,] 0.5238095 0.5652174 0.6000000
matrix1 ˆ 2 # square
[,1] [,2] [,3]
[1,] 100 144 196
[2,] 121 169 225
matrix1 - 2*matrix2 # subtraction
[,1] [,2] [,3]
[1,] -30 -32 -34
[2,] -31 -33 -35
matrix1 %*% matrix2 # multiplication
Error in matrix1 %*% matrix2: non-conformable arguments
For matrix multiplication, the number of columns in the first matrix must be equal to the number of rows in the second matrix. The resulting matrix, known as the matrix product, has the number of rows of the first and the number of columns of the second matrix.
In previous example, the matrix multiplication won’t work. Let’s change the number of columns of matrix1 and perform the matrix multiplication.
matrix1 <- matrix(c(10:15),ncol=2)
matrix1
[,1] [,2]
[1,] 10 13
[2,] 11 14
[3,] 12 15
matrix2 <- matrix(c(20:25),nrow=2)
matrix2
[,1] [,2] [,3]
[1,] 20 22 24
[2,] 21 23 25
matrix1 %*% matrix2
[,1] [,2] [,3]
[1,] 473 519 565
[2,] 514 564 614
[3,] 555 609 663
Summary
Matrices are two dimensional vectors. They inherit all the object properties from vectors. Matrices are crucial when working with linear systems such as multiple regression modelling. In this article, we created matrix, subset them using different methods, and run arithmetic operations on two matrices.
Vectors and matrices are sufficient for many use cases. However, some particular problems need a data structure with even higher dimensions. In the next article, we will briefly introduce arrays and you will see how these data structures share similar behaviors.