# Like vectors, matrices store a collection of scalar-elements of the same type
# (double, logicals or strings). Unlike vectors, they do so along two (rather
# than one) dimension.
Creation
mA = matrix(NA, ncol = 3, nrow = 2) # matrix of NAs (to be filled-in)
# create a matrix by filling-in elements of a vector:
vx = c(4.3, 5, 6, 3, 4.5, 9.2)
# by column:
mA <- matrix(vx, ncol = 3, nrow = 2)
# by row:
mA <- matrix(vx, ncol = 3, nrow = 2, byrow = TRUE)
# As you can verify, mA is of type 'double' (and 'numeric') as opposed to
# 'logical' or 'character' (string):
typeof(mA)
is.double(mA)
is.numeric(mA)
# It is also a matrix rather than a vector:
is.matrix(mA)
is.vector(mA)
# We can use the following command to vectorize the matrix mA (i.e. turn it
# into a vector by stacking its columns on top of each other) or to ensure that
# a $n \times 1$ matrix is treated as a vector by R:
as.vector(mA)
## [1] 4.3 3.0 5.0 4.5 6.0 9.2
mB <- matrix(1:4, ncol = 3, nrow = 4)
is.vector(mB)
## [1] FALSE
mB_ <- as.vector(mB)
is.vector(mB_)
## [1] TRUE
# Further ways to create a matrix:
diag(3) # 3x3 identity matrix
diag(c(3, 2)) # 2x2 diagonal matrix with 3 and 2 on diagonal
# But: Note: when applied to an existing, symmetric matrix, diag() returns its
# diagonal:
mA = matrix(1:9, ncol = 3, nrow = 3)
diag(mA)
# Create a matrix by putting the same vector in each column:
vx = c(1, 5, 3, 6)
mA = replicate(5, vx)
# Create a matrix as the Cartesian product of two vectors:
vx = seq(0, 0.1, 0.02)
vy = seq(0.1, 0.3, 0.1)
mB = expand.grid(column1 = vx, column2 = vy)
# To display the matrix, you can use the commands 'show' and 'print', as
# before. Also, in contrast to scalars and vectors, you can click on the
# matrix in the environment window, which opens up a separate panel in the
# script-window to show you the matrix.
# We can, in principle also create a matrix of logicals or strings:
matrix(c(TRUE, FALSE, FALSE, FALSE, TRUE, FALSE), ncol = 3, nrow = 2)
matrix(c("a", "b", "c", "d", "e", "f"), ncol = 3, nrow = 4)
replicate(3, c(TRUE, FALSE))
replicate(3, c("a", "b"))
# This is rarely done in practice. However, matrices of logicals or strings
# can arise when applying a function to a matrix (of numbers). For example,
# matrices of logicals arise when comparing elements of a matrix to some
# number.
Indexing
mA = matrix(1:9, ncol = 3, nrow = 3)
dim(mA) #display number of rows and columns of matrix mA
nrow(mA)
ncol(mA)
colnames(mA) = c("a", "b", "c") #label columns of matrix
rownames(mA) = c("r1", "r2", "r3")
# Again, three ways of indexing possible:
# 1. 'Direct'
mA[1, 2] # access element (1,2)
mA[1, ] # access first row, returns vector
mA[, 1] # access first column, returns vector
mA[c(1, 2), c(1, 3)] # access specified rows and columns
# 2. Using logicals:
mA[c(TRUE, FALSE, FALSE), c(FALSE, TRUE, FALSE)]
mA[c(TRUE, FALSE, FALSE), ]
# 3. Using row/column names:
mA["r1", "b"]
mA["r1", ]
# And, with two dimensions available, we can mix these indexing approaches:
mA[1, "b"]
mA[c(TRUE, FALSE, FALSE), "b"]
# ...
Basic Operations
mA = matrix(c(1, 3, 8, 8), ncol = 2, nrow = 2)
mB = matrix(c(1, 2, 7, 1), ncol = 2, nrow = 2)
mA * mB # element-wise multiplication
mA %*% mB # matrix multiplication
t(mA) # transpose
solve(mA) # inverse
solve(mA, tol = 1e-23) # if almost singular
# often, need to convert : as.numeric()
library(Matrix)
rankMatrix(mA) # compute rank
eigen(mA) # compute eigenvalues and eigenvectors;
eigen(mA)$values
eigen(mA)$vectors
# Many of the functions applied above to numbers and vectors can also be
# applied to matrices: e.g.
sqrt(mA) # compute square-root for each element of matrix
min(mA) # compute minimum out of all elements of matrix
mean(mA) # mean of all elements in matrix
mA >= 2 # element-wise comparison, returns matrix of logicals
# Some functions only make sense when their single input is a matrix (not a
# vector or a scalar):
cov(mA) # covariance between columns
cor(mA) # correlation between columns
# A particularly useful function for matrices is 'apply'. It allows us e.g. to
# apply a function designed for a vector to each column or row of a matrix
# separately:
mA = matrix(c(1, 3, 2, 8), ncol = 2, nrow = 2)
# for each column (=2nd dimension) of mA, compute the mean of elements:
apply(mA, 2, mean)
# (i.e. apply to object mA, on dimension 2 (i.e. by columns), the function
# 'mean'
# One can also supply a self-written function to 'apply':
fDemean = function(vx) {
vx - mean(vx)
}
apply(mA, 2, fDemean)
# or, in short:
apply(mA, 2, function(vx) {
vx - mean(vx)
})
# This is useful even for functions applied to each element of a matrix:
apply(mA, c(1, 2), function(x) {
min(2, x)
}) # since min(mA,x) doesn't give the hoped for result
Arrays
# Arrays generalize matrices, as they store a collection of scalar-elements of
# the same type (double, logicals or strings) along a general number of
# dimensions (more than 2). They are useful for efficiently storing data that
# differ along several dimensions (e.g. countries, years, variables, ...) and
# accessing subsets of it.
# Create three-dimensional array of NAs:
aY = array(dim = c(2, 3, 2))
# Create three-dimensional array by using a vector to 'fill it up':
aX = c(1:12)
dim(aX) = c(2, 3, 2)
print(aX)
## , , 1
##
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
##
## , , 2
##
## [,1] [,2] [,3]
## [1,] 7 9 11
## [2,] 8 10 12
# Indexing of arrays:
aX[1, 3, 2]
aX[, c(2:3), 1]
aX[1, c(2:3), ] # returns matrix (2 x 2)
aX[1, c(2:3), , drop = FALSE] # returns array (1 x 2 x 2)
# Can index similarly by using logical-vectors for each dimension, or by using
# the names of the elements in the different dimensions:
# Name dimensions of array:
dimnames(aX)[[1]] = c("r1", "r2")
dimnames(aX)[[2]] = c("a", "b", "c")
dimnames(aX)[[3]] = c("A", "B")
# Functions that operate on scalars can be used on arrays as well:
# Functions:
sqrt(aX) # compute square-root of each element
# There are (to my knowledge) no built-in functions that require a single array
# as an argument.
# We can use the function 'apply' to apply a function along different
# dimensions of an array:
# for each row and column, compute sum along third dimension:
apply(aX, c(1, 2), sum)
# for each row, compute minimum of resulting matrix:
apply(aX, 1, min)