What is a Matrix in R?

A matrix is a two dimensional rectangular data set. It can be created using a vector input to the matrix function. The matrix function is represented as matrix(value, nrow, ncol, byrow, dimnames)

It is possible to create a matrix of character values. The following example creates 2 by 3 matrix and whose elements are character values. nrow and ncol arguments were set to 2 and 3 respectively while the byrow argument were set to TRUE to specifies that the matrix should be arranged in rows.

matrix( c('a', 'a', 'b', 'c', 'b', 'a'), nrow=2, ncol=3, byrow = TRUE)
##      [,1] [,2] [,3]
## [1,] "a"  "a"  "b" 
## [2,] "c"  "b"  "a"

Another example is to create a matrix with numerical elements. The code below creates a 3 by 3 matrix as follows,

matrix(c(12, 23, 45, 13, 30, 20, 32, 33, 40), nrow=3, byrow = TRUE)
##      [,1] [,2] [,3]
## [1,]   12   23   45
## [2,]   13   30   20
## [3,]   32   33   40

Also, it is possible to specify names of each row and column with the dimnames argument. To demonstrates this, we applied the previous examples and its gives the following output

matrix(c(12, 23, 45, 13, 30, 20, 32, 33, 40), nrow=3, byrow = TRUE, dimnames =list(c("one", "two", "third"), c("col1", "col2", "col3")))
##       col1 col2 col3
## one     12   23   45
## two     13   30   20
## third   32   33   40

Index matrices

Like vectors, elements of a matrix can also be accessed through indexing. One way of doing this is through double indexing in a square bracket such as “x[row, column]”. The first is for the row’s number and the second for the column’s number.

The following codes show matrix indexing using double indexing and they both return single element.

x <- matrix(1:9, nrow = 3, byrow = TRUE)
colnames(x) <- c("col1", "col2", "col3")
x[1, 2] #Return element at first row, second column.
## col2 
##    2
x[3, 3] # Return element at third row, third column.
## col3 
##    9

Matrix can return multiple elements at the same time. To demonstrate this example, we shall make use of previous example for the examples that follow. The first code returns a 2 by 2 matrix. The second code returns all rows in the second column. The third code returns all the columns in the second row.

x <- matrix(1:9, nrow = 3, byrow = TRUE)
colnames(x) <- c("col1", "col2", "col3")
x[1:2, 1:2]
##      col1 col2
## [1,]    1    2
## [2,]    4    5
x[, 2]
## [1] 2 5 8
x[2, ]
## col1 col2 col3 
##    4    5    6

It is possible to use column name for sub setting. For instance, using the matrix created from the previous example, the first code returns all elements from the first column “col1”. The second code returns all elements from the second and third columns respectively.

x <- matrix(1:9, nrow = 3, byrow = TRUE)
colnames(x) <- c("col1", "col2", "col3")
x[, "col1"]  #Returns elements from the first column
## [1] 1 4 7
x[, c("col2", "col3")] #Returns second elements 
##      col2 col3
## [1,]    2    3
## [2,]    5    6
## [3,]    8    9
x <- matrix(1:9, nrow = 3, byrow = TRUE)
colnames(x) <- c("col1", "col2", "col3")
x[1:2, 1:2]
##      col1 col2
## [1,]    1    2
## [2,]    4    5
x[, 2]
## [1] 2 5 8
x[2, ]
## col1 col2 col3 
##    4    5    6

Instead of indexing with double number, it is possible to index with single number as shown below. The first and second index returns 10 and 18 respectively because elements are in index 5 and 9 respectively.

x <- matrix(c(2, 4, 6, 8, 10, 12, 14, 16, 18), nrow = 3, byrow = TRUE)
colnames(x) <- c("col1", "col2", "col3")
x[5]
## [1] 10
x[9]
## [1] 18

Additionally, it should be noted that the following code returns a vector when indexing the second column of the matrix from the previous example. To return a matrix form, we apply “drop = FALSE” argument when indexing matrix. For instance, the following indexing returns two results: before and after applying “drop=FALSE”.

x <- matrix(c(2, 4, 6, 8, 10, 12, 14, 16, 18), nrow = 3, byrow = TRUE)
colnames(x) <- c("col1", "col2", "col3")
x[, 2]  #Return a vector 
## [1]  4 10 16
x[, 2, drop = FALSE]   #Return a matrix
##      col2
## [1,]    4
## [2,]   10
## [3,]   16

Other situation might arise when we want to change element or group of elements of a matrix at a particular index. The following codes indexing, show how how we can change the element of a matrix at an index position. From the output, the first indexing change element at the row 2 column 2 from 10 to 20. Also, the second indexing change all elements in the third column from 6, 12 and 18 to 13, 14 and 23 respectively.

x <- matrix(c(2, 4, 6, 8, 10, 12, 14, 16, 18), nrow = 3, byrow = TRUE)
colnames(x) <- c("col1", "col2", "col3")
x[2, 2] <- 20 #Change single element 
x[, 3] <- c(13, 14, 23)
x
##      col1 col2 col3
## [1,]    2    4   13
## [2,]    8   20   14
## [3,]   14   16   23

Matrix Operations

One of the advantages of R is that we could perform arithmetic operations on matrices. The result of the operation is also a matrix.

Furthermore, the dimensions (number of rows and columns) of matrices involved in the operation should be the same.

Matrix Addition and Subtraction

We start by creating two matrices using the matrix() function discussed from previous page. The matrices will be save as an object as “matrix_one” and “matrix_two” and they are of the same dimension. The output shows addition and subtraction of two matrices.

#Create two matrix
matrix_one <- matrix(seq(3, 19, by = 2), nrow = 3)
matrix_one
##      [,1] [,2] [,3]
## [1,]    3    9   15
## [2,]    5   11   17
## [3,]    7   13   19
matrix_two <- matrix(seq(2, 18, by = 2), nrow = 3)
matrix_two
##      [,1] [,2] [,3]
## [1,]    2    8   14
## [2,]    4   10   16
## [3,]    6   12   18
#Add the matrix_one and matrix_two  together
result <- matrix_one + matrix_two 
cat("Result of addition", "\n")
## Result of addition
result
##      [,1] [,2] [,3]
## [1,]    5   17   29
## [2,]    9   21   33
## [3,]   13   25   37
#Subtract the matrix_two from matrix_one
result <- matrix_one - matrix_two
cat("Result of substraction", "\n")
## Result of substraction
result
##      [,1] [,2] [,3]
## [1,]    1    1    1
## [2,]    1    1    1
## [3,]    1    1    1

Matrix Multiplication and Division

#Create two matrix
matrix_one <- matrix(seq(3, 19, by = 2), nrow = 3)
matrix_one
##      [,1] [,2] [,3]
## [1,]    3    9   15
## [2,]    5   11   17
## [3,]    7   13   19
matrix_two <- matrix(seq(2, 18, by = 2), nrow = 3)
matrix_two
##      [,1] [,2] [,3]
## [1,]    2    8   14
## [2,]    4   10   16
## [3,]    6   12   18
#Multiply the matrices
result <- matrix_one * matrix_two
cat("Result of multiplication", "\n")
## Result of multiplication
result
##      [,1] [,2] [,3]
## [1,]    6   72  210
## [2,]   20  110  272
## [3,]   42  156  342
#Divide the matrices
result <- matrix_one / matrix_two
cat("Result of division", "\n")
## Result of division
result
##          [,1]     [,2]     [,3]
## [1,] 1.500000 1.125000 1.071429
## [2,] 1.250000 1.100000 1.062500
## [3,] 1.166667 1.083333 1.055556

Also, the diag() function returns the elements at the diagonal. Using the matrix_one from the example above, find elements at its diagonal.

matrix_one <- matrix(seq(3, 19, by = 2), nrow = 3)
diag(matrix_one)
## [1]  3 11 19

Apply cbind() and rbind()

Two matrices can be combined together to form a single column matrix or a row matrix. Apply the cbind() function to combine two of more vectors or matrices as columns. Also, the rbind() function combine two or more vectors or matrices as rows. From the first output, two matrices are combined together as a column using the cbind() function. Also, the rbind() function was combined as a row to form a matrix.

#Create two matrices 
matrix_one <- matrix(seq(3, 19, by = 2), nrow = 3)
matrix_one
##      [,1] [,2] [,3]
## [1,]    3    9   15
## [2,]    5   11   17
## [3,]    7   13   19
matrix_two <- matrix(seq(2, 18, by = 2), nrow = 3)
matrix_two
##      [,1] [,2] [,3]
## [1,]    2    8   14
## [2,]    4   10   16
## [3,]    6   12   18
#Apply the rbind() function
matrixRbind <- rbind(matrix_one, matrix_two)
cat("Result of rbind()", "\n")
## Result of rbind()
matrixRbind
##      [,1] [,2] [,3]
## [1,]    3    9   15
## [2,]    5   11   17
## [3,]    7   13   19
## [4,]    2    8   14
## [5,]    4   10   16
## [6,]    6   12   18
matrixCbind <- cbind(matrix_one, matrix_two)
cat("Result of cbind()", "\n")
## Result of cbind()
matrixCbind
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    3    9   15    2    8   14
## [2,]    5   11   17    4   10   16
## [3,]    7   13   19    6   12   18

Arrays

Arrays are R data objects which can store data in more than two dimensions. For instance, an array of this dimension (2, 3, 4) creates 4 rectangular matrices each with 2 rows and 3 columns. Array can only store the same data type.

An array is created with the array(data = NA, dim = length(data), dimnames = NULL) with the following arguments.

For the following example, two different vectors of different lengths were created and they were called into the array function to create a 3 by 3 matrix in two dimensions.

#Create two different vectors and each having different length
vector_one <- c(7, 9, 10)
vector_two <- c(3, 6, 7, 12, 13, 16)

#Then make this vector to be an input in  array function.
result <- array(c(vector_one, vector_two), dim = c(3, 3, 2))
result
## , , 1
## 
##      [,1] [,2] [,3]
## [1,]    7    3   12
## [2,]    9    6   13
## [3,]   10    7   16
## 
## , , 2
## 
##      [,1] [,2] [,3]
## [1,]    7    3   12
## [2,]    9    6   13
## [3,]   10    7   16

Naming columns and rows of an array

Name each row, column and matrix created from the previous code and this done with the “dimnames” arguments in the array function. In addition to the two vectors created from earlier, we shall create column, row and matrix names and to this, we use “dimnames” arguments as shown with the following codes.

#Create a vectors, row name, column names and #matrices name.
vector_one <- c(7, 9, 10)
vector_two <- c(3, 6, 7, 12, 13, 16)
column_names <- c("col1", "col2", "col3") 
row_names <- c("row1", "row2", "row3")
matrix_names <- c("matrix_one", "matrix_two")

result <- array(c(vector_one, vector_two), dim = c(3, 3, 2), dimnames = list(row_names, column_names,  matrix_names))

result 
## , , matrix_one
## 
##      col1 col2 col3
## row1    7    3   12
## row2    9    6   13
## row3   10    7   16
## 
## , , matrix_two
## 
##      col1 col2 col3
## row1    7    3   12
## row2    9    6   13
## row3   10    7   16

Indexing Array Elements

Indexing in R is done in three dimensions using the following array[i, j, k] method where “i” stands for row indexing, “j” stands for column indexing, and “k” stands for the matrix that will be index. We shall use the previous example to illustrate the array indexing. The first output gives second row of the second matrix. The second indexing returns element at the first row, third column for the first matrix. The last indexing returns the second matrix.

#Create a vectors, row name, column names and #matrices name.
vector_one <- c(7, 9, 10)
vector_two <- c(3, 6, 7, 12, 13, 16)
column_names <- c("col1", "col2", "col3") 
row_names <- c("row1", "row2", "row3")
matrix_names <- c("matrix_one", "matrix_two")

result <- array(c(vector_one, vector_two), dim = c(3, 3, 2), dimnames = list(row_names, column_names,  matrix_names))

#Output the first row of the second matrix
result[1,,2]
## col1 col2 col3 
##    7    3   12
#Output the element at first row, third column at the first matrix
result[1, 3, 1]
## [1] 12
#Output the second matrix
result[,,2]
##      col1 col2 col3
## row1    7    3   12
## row2    9    6   13
## row3   10    7   16

Arithmetic Operation Across Array Elements

It is possible to do arithmetic calculation across the elements in an array using the apply() function. The syntax is apply(x, margin, fun)

  • x - Stands for an array or matrix of elements

  • Margin - This take a value 1 or 2 to specify to apply the function. If margin = 1, means apply the function to the row. If the margin = 2, means apply the function to the column.

  • Fun - Tells which function to apply. We could apply mean, max, sum or even user defined function.

#Create a vectors, row name, column names and #matrices name.
vector_one <- c(7, 9, 10)
vector_two <- c(3, 6, 7, 12, 13, 16)
column_names <- c("col1", "col2", "col3") 
row_names <- c("row1", "row2", "row3")
matrix_names <- c("matrix_one", "matrix_two")

result <- array(c(vector_one, vector_two), dim = c(3, 3, 2), dimnames = list(row_names, column_names,  matrix_names))

result 
## , , matrix_one
## 
##      col1 col2 col3
## row1    7    3   12
## row2    9    6   13
## row3   10    7   16
## 
## , , matrix_two
## 
##      col1 col2 col3
## row1    7    3   12
## row2    9    6   13
## row3   10    7   16
#Use apply function to calculate the sum of the rows across all the matrices.
array_arith <- apply(result, c(1), sum)
array_arith
## row1 row2 row3 
##   44   56   66