Scalar addition and subtraction on a matrix works identically to addition or subtraction on a vector.
We simply use the standard addition (+
) and subtraction (-
) operators.
a <- matrix(1:6, nrow = 2)
a
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
a + 1
## [,1] [,2] [,3]
## [1,] 2 4 6
## [2,] 3 5 7
a - 2
## [,1] [,2] [,3]
## [1,] -1 1 3
## [2,] 0 2 4
Scalar multiplication and division also work with the standard operators (*
and /
).
a * 2
## [,1] [,2] [,3]
## [1,] 2 6 10
## [2,] 4 8 12
a/2
## [,1] [,2] [,3]
## [1,] 0.5 1.5 2.5
## [2,] 1.0 2.0 3.0
As with a vector, it is possible to apply comparators to an entire matrix:
a > 2
## [,1] [,2] [,3]
## [1,] FALSE TRUE TRUE
## [2,] FALSE TRUE TRUE
We can then use the resulting logical matrix as an index:
a[a > 2]
## [1] 3 4 5 6
But the result is a vector, not a matrix. If we use the same statement to assign, however, the result is a matrix:
a[a > 2] <- 99
a
## [,1] [,2] [,3]
## [1,] 1 99 99
## [2,] 2 99 99
In statistics, an important operation is matrix multiplication. Unlike scalar multiplication, this procedure involves the multiplication of two matrices by one another.
Let's start by defining a function to demonstrate how matrix multiplication works:
mmdemo <- function(A, B) {
m <- nrow(A)
n <- ncol(B)
C <- matrix(NA, nrow = m, ncol = n)
for (i in 1:m) {
for (j in 1:n) {
C[i, j] <- paste("(", A[i, ], "*", B[, j], ")", sep = "", collapse = "+")
}
}
print(C, quote = FALSE)
}
Now let's generate two matrices, multiply them and see how it worked:
amat <- matrix(1:4, ncol = 2)
bmat <- matrix(1:6, nrow = 2)
amat
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
bmat
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
amat %*% bmat
## [,1] [,2] [,3]
## [1,] 7 15 23
## [2,] 10 22 34
mmdemo(amat, bmat)
## [,1] [,2] [,3]
## [1,] (1*1)+(3*2) (1*3)+(3*4) (1*5)+(3*6)
## [2,] (2*1)+(4*2) (2*3)+(4*4) (2*5)+(4*6)
Let's try it on a different set of matrices:
amat <- matrix(1:16, ncol = 4)
bmat <- matrix(1:32, nrow = 4)
amat
## [,1] [,2] [,3] [,4]
## [1,] 1 5 9 13
## [2,] 2 6 10 14
## [3,] 3 7 11 15
## [4,] 4 8 12 16
bmat
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 1 5 9 13 17 21 25 29
## [2,] 2 6 10 14 18 22 26 30
## [3,] 3 7 11 15 19 23 27 31
## [4,] 4 8 12 16 20 24 28 32
amat %*% bmat
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 90 202 314 426 538 650 762 874
## [2,] 100 228 356 484 612 740 868 996
## [3,] 110 254 398 542 686 830 974 1118
## [4,] 120 280 440 600 760 920 1080 1240
mmdemo(amat, bmat)
## [,1] [,2]
## [1,] (1*1)+(5*2)+(9*3)+(13*4) (1*5)+(5*6)+(9*7)+(13*8)
## [2,] (2*1)+(6*2)+(10*3)+(14*4) (2*5)+(6*6)+(10*7)+(14*8)
## [3,] (3*1)+(7*2)+(11*3)+(15*4) (3*5)+(7*6)+(11*7)+(15*8)
## [4,] (4*1)+(8*2)+(12*3)+(16*4) (4*5)+(8*6)+(12*7)+(16*8)
## [,3] [,4]
## [1,] (1*9)+(5*10)+(9*11)+(13*12) (1*13)+(5*14)+(9*15)+(13*16)
## [2,] (2*9)+(6*10)+(10*11)+(14*12) (2*13)+(6*14)+(10*15)+(14*16)
## [3,] (3*9)+(7*10)+(11*11)+(15*12) (3*13)+(7*14)+(11*15)+(15*16)
## [4,] (4*9)+(8*10)+(12*11)+(16*12) (4*13)+(8*14)+(12*15)+(16*16)
## [,5] [,6]
## [1,] (1*17)+(5*18)+(9*19)+(13*20) (1*21)+(5*22)+(9*23)+(13*24)
## [2,] (2*17)+(6*18)+(10*19)+(14*20) (2*21)+(6*22)+(10*23)+(14*24)
## [3,] (3*17)+(7*18)+(11*19)+(15*20) (3*21)+(7*22)+(11*23)+(15*24)
## [4,] (4*17)+(8*18)+(12*19)+(16*20) (4*21)+(8*22)+(12*23)+(16*24)
## [,7] [,8]
## [1,] (1*25)+(5*26)+(9*27)+(13*28) (1*29)+(5*30)+(9*31)+(13*32)
## [2,] (2*25)+(6*26)+(10*27)+(14*28) (2*29)+(6*30)+(10*31)+(14*32)
## [3,] (3*25)+(7*26)+(11*27)+(15*28) (3*29)+(7*30)+(11*31)+(15*32)
## [4,] (4*25)+(8*26)+(12*27)+(16*28) (4*29)+(8*30)+(12*31)+(16*32)
Note: matrix multiplication is noncommutative, so the order of matrices matters in a statement!
Another important operation is the crossproduct. See also: OLS in matrix form.
Sometimes we want to calculate a sum or mean for each row or column of a matrix. R provides built-in functions for each of these operations:
cmat <- matrix(1:20, nrow = 5)
cmat
## [,1] [,2] [,3] [,4]
## [1,] 1 6 11 16
## [2,] 2 7 12 17
## [3,] 3 8 13 18
## [4,] 4 9 14 19
## [5,] 5 10 15 20
rowSums(cmat)
## [1] 34 38 42 46 50
colSums(cmat)
## [1] 15 40 65 90
rowMeans(cmat)
## [1] 8.5 9.5 10.5 11.5 12.5
colMeans(cmat)
## [1] 3 8 13 18
These functions can be helpful for aggregating multiple variables and performing the sum or mean with these functions is much faster than manually adding (or taking the mean) of columns using +
and /
operators.