1 Basic Definitions and Functions
1.1 The matrix() Function
1.2 The Dimension of a Matrix
1.3 The cbind() and rbind() Functions
1.4 Matrices Are Two-Dimensional Vectors
2 Naming Rows and Columns of Two-Dimensional Objects
3 Extracting Data From Two-Dimensional Objects
3.1 Numeric Indices
3.2 Logical Indices
3.3 Named (Character) Indices
4 Matrix Operations
4.1 Entrywise Arithmetic Operations
4.2 Matrix Multiplication
4.3 The Identity Matrix
4.4 The Inverse of a Matrix
5 Operations on Matrix Columns and Rows
Create matrices with matrix(), rbind(), and cbind().
Understand how R stores and performs operations on matrices.
Add row and column names to two-dimensional objects.
Extract and assign values to two-dimensional objects.
Differentiate between * and %*% for matrices.
Compute the inverse of a square matrix
matrix() function: creates a two-dimensional (rectangular) array of values. Every value in a matrix must be of the same variable_type
#takes in a vector and arranges it in nrow, ncol
one_to_six <- seq(1,6) # data
matrix(one_to_six, nrow = 3, ncol = 2)
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
byrow = FALSE, which means R will fill the matrix by column
#takes in a vector and arranges it in nrow, ncol
one_to_six <- seq(1,6) # data
matrix(one_to_six, nrow = 2, ncol = 3, byrow = TRUE) # fills matrix by row first
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
matrix(one_to_six, nrow = 2, ncol = 3, byrow = FALSE) # fills matrix by col first
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
Side note: The default values are nrow = 1 and ncol = 1, furthermore : recycling occurs:
matrix(1:4, nrow = 2, ncol = 6) # Complete recycling: no warning thrown (amount recycled is intiger divisible)
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 3 1 3 1 3
## [2,] 2 4 2 4 2 4
matrix(1:4, nrow = 2, ncol = 5) # Incomplete recycling: warning thrown (amount recycled is decimal divisible)
## Warning in matrix(1:4, nrow = 2, ncol = 5): data length [4] is not a
## sub-multiple or multiple of the number of columns [5]
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 3 1 3 1
## [2,] 2 4 2 4 2
Dimension of a Matrix: dim() : the number of rows and the number of columns, often written as nrow × ncol, read aloud as “nrow by ncol”.
A <- matrix(1:6, nrow = 3, ncol = 2)
print("This Matrix has:")
## [1] "This Matrix has:"
dim(A)[1]
## [1] 3
print("rows and, this many col: ")
## [1] "rows and, this many col: "
dim(A)[2]
## [1] 2
print("here is the matrix: ")
## [1] "here is the matrix: "
A
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
Side note: rows = height, col = width
A <- matrix(1:6, nrow = 3, ncol = 2)
nrow(A)
## [1] 3
ncol(A)
## [1] 2
#create matrix by each col entry.
a <- c(1,2)
b <- c(2,3)
c <- c(4,5)
cbind(a,b,c)
## a b c
## [1,] 1 2 4
## [2,] 2 3 5
#create matrix by each row entry.
d <- c(1,2)
e <- c(3,4)
f <- c(5,6)
rbind(d,e,f)
## [,1] [,2]
## d 1 2
## e 3 4
## f 5 6
Side note:
If the number of columns or rows match in a way that makes sense, i.e., they are conformable. Meaning, you can combine matrices.
# Test function:
conformable_matrix <- function(matrix_1, matrix_2){
if (is.null(dim(matrix_1))| is.null(dim(matrix_2))){
print("One or more of these are not Matrices! Please Try Again")
} else {
if (nrow(matrix_1) == nrow(matrix_2) & ncol(matrix_1) == ncol(matrix_2)){
print("Conformable Matrices!")
print("Therefore, you CAN use cbind() or rbind() to combine those matrices")
} else {
print("Non-Conformable Matrices!")
print("Therefore, you CANNOT use cbind() or rbind() to combine those matrices")
}
}
}
#Matrices
A <- matrix(1:6, nrow = 2, ncol = 3)
B <- matrix(1:6, nrow = 2, ncol = 3)
C <- matrix(1:6, nrow = 3, ncol = 2)
# Test for conformability:
conformable_matrix(A,B)
## [1] "Conformable Matrices!"
## [1] "Therefore, you CAN use cbind() or rbind() to combine those matrices"
conformable_matrix(A,C)
## [1] "Non-Conformable Matrices!"
## [1] "Therefore, you CANNOT use cbind() or rbind() to combine those matrices"
conformable_matrix(A,c(1,2,3))
## [1] "One or more of these are not Matrices! Please Try Again"
my_list <- list(name = "Alice", age = 25, scores = c(90, 85, 88))
my_list
## $name
## [1] "Alice"
##
## $age
## [1] 25
##
## $scores
## [1] 90 85 88
my_list <- list(name = "Alice", age = 25, scores = c(90, 85, 88))
attributes(my_list)
## $names
## [1] "name" "age" "scores"
#recall that all matrices are just vectors with a dimension attribute:
A <- matrix(1:6, ncol = 3, nrow = 2)
A
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
# Converted back to vector by saying attributes dont exist (NULL)
attributes(A) <- NULL
A
## [1] 1 2 3 4 5 6
# Vector:
A <- seq(1,6)
A
## [1] 1 2 3 4 5 6
# Matrix:
attributes(A) <- list("dim" = c(3,2)) # 3 rows by 2 col
A
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
A <- matrix(1:6, nrow = 3, ncol = 2)
A
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
attr(A, "dim") <- NULL
A
## [1] 1 2 3 4 5 6
| Name | Height (inches) | Weight (pounds) | Income ($/month) |
|---|---|---|---|
| Leslie | 62 | 115 | 4000 |
| Ron | 71 | 201 | NA |
| April | 66 | 119 | 2000 |
How would we format this data in R to maintain the row and col names?
SLOW WAY:
#matrix values
numeric_values <- cbind(c(62,71,66), c(115, 201, 119), c(4000, NA, 2000))
#row names
rownames(numeric_values) <- c("leslie", "Ron", "April")
#col names
colnames(numeric_values) <- c("Height", "Weight", "Income")
labeled_matrix <- numeric_values
labeled_matrix
## Height Weight Income
## leslie 62 115 4000
## Ron 71 201 NA
## April 66 119 2000
#notice:
attributes(labeled_matrix)
## $dim
## [1] 3 3
##
## $dimnames
## $dimnames[[1]]
## [1] "leslie" "Ron" "April"
##
## $dimnames[[2]]
## [1] "Height" "Weight" "Income"
QUICK WAY:
numeric_values <- cbind(c(62,71,66), c(115, 201, 119), c(4000, NA, 2000))
dimnames(numeric_values) <- list(c("leslie", "Ron", "April"), c("Height", "Weight", "Income"))
numeric_values
## Height Weight Income
## leslie 62 115 4000
## Ron 71 201 NA
## April 66 119 2000
Fun Fact:
one_line <- matrix(c(62, 71, 66, 115, 201, 119, 4000, NA, 2000), nrow = 3, byrow = FALSE,
dimnames = list(c("Leslie", "Ron", "April"),
c("Height", "Weight", "Income")))
one_line
## Height Weight Income
## Leslie 62 115 4000
## Ron 71 201 NA
## April 66 119 2000
rbind("row 1" = 1:3, "row 2" = 4:6, "row 3" = 7:9)
## [,1] [,2] [,3]
## row 1 1 2 3
## row 2 4 5 6
## row 3 7 8 9
cbind("col 1" = 1:3, "col 2" = 4:6, "col 3" = 7:9)
## col 1 col 2 col 3
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
B <- matrix(1:9, nrow = 3, ncol = 3)
B
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
row = 1
col = 3
B[row,col]
## [1] 7
B[row,]
## [1] 1 4 7
B[,col]
## [1] 7 8 9
identical(B[,], B)
## [1] TRUE
B <- matrix(1:9, nrow = 3, ncol = 3)
#logical indexing:
B[B > 4]
## [1] 5 6 7 8 9
# Logical Indexing for specific index:
one_line <- matrix(c(62, 71, 66, 115, 201, 119, 4000, NA, 2000), nrow = 3, byrow = FALSE,
dimnames = list(c("Leslie", "Ron", "April"),
c("Height", "Weight", "Income")))
one_line
## Height Weight Income
## Leslie 62 115 4000
## Ron 71 201 NA
## April 66 119 2000
taller_than_leslie <- one_line[1,] > 62
one_line[taller_than_leslie, ]
## Height Weight Income
## Ron 71 201 NA
## April 66 119 2000
h_w_i_data <- matrix(c(62, 71, 66, 115, 201, 119, 4000, NA, 2000), nrow = 3, byrow = FALSE,
dimnames = list(c("Leslie", "Ron", "April"),
c("Height", "Weight", "Income")))
#only Leslie
h_w_i_data["Leslie", ]
## Height Weight Income
## 62 115 4000
# Everyone except Leslie
everyone_except_leslie <- h_w_i_data[rownames(h_w_i_data) != "Leslie", ]
everyone_except_leslie
## Height Weight Income
## Ron 71 201 NA
## April 66 119 2000
#How tall is leslie?
h_w_i_data["Leslie", "Height"]
## [1] 62
A <- matrix(c(1), nrow = 3, ncol = 3)
# Any normal arithmatic operations can occur to each
A + 1
## [,1] [,2] [,3]
## [1,] 2 2 2
## [2,] 2 2 2
## [3,] 2 2 2
# Adding matrixes:
B <- matrix(c(4), nrow = 3, ncol = 3)
# Entry wise addition between matrices:
C <- B + A
C
## [,1] [,2] [,3]
## [1,] 5 5 5
## [2,] 5 5 5
## [3,] 5 5 5
A <- matrix(seq(1,6), nrow = 3, ncol = 2)
A
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
B <- matrix(c(1), nrow = 2, ncol = 3)
B
## [,1] [,2] [,3]
## [1,] 1 1 1
## [2,] 1 1 1
#matrix multiplication: dot product:
A%*%B
## [,1] [,2] [,3]
## [1,] 5 5 5
## [2,] 7 7 7
## [3,] 9 9 9
identity_matrix <- diag(3)
identity_matrix
## [,1] [,2] [,3]
## [1,] 1 0 0
## [2,] 0 1 0
## [3,] 0 0 1
diag(c(1,2,3))
## [,1] [,2] [,3]
## [1,] 1 0 0
## [2,] 0 2 0
## [3,] 0 0 3
#The nrow and ncol arguments can also be used to specify the dimensions for a rectangular (non-square) matrix.
diag(c(1,2), nrow = 2, ncol = 3)
## [,1] [,2] [,3]
## [1,] 1 0 0
## [2,] 0 2 0
A <- matrix(1:4, ncol = 2, nrow = 2)
#computes inverse:
solve(A)
## [,1] [,2]
## [1,] -2 1.5
## [2,] 1 -0.5
#proof it is the inverse: should be identity matrix
solve(A) %*% A
## [,1] [,2]
## [1,] 1 0
## [2,] 0 1
SIDE NOTES:
The inverse DOESNT ALWAYS exist!
A matrix with an inverse is called: non-singular or invertible
A matrix that cant be solved is called: singular
vapply() function applies some function to each element of a vector. apply() function: applies a function to the rows or columns of a matrix or data frame
h_w_i_data <- matrix(c(62, 71, 66, 115, 201, 119, 4000, NA, 2000), nrow = 3, byrow = FALSE,
dimnames = list(c("Leslie", "Ron", "April"),
c("Height", "Weight", "Income")))
h_w_i_data
## Height Weight Income
## Leslie 62 115 4000
## Ron 71 201 NA
## April 66 119 2000
#Find mean of each row
apply(h_w_i_data, 1, mean, na.rm = TRUE)
## Leslie Ron April
## 1392.3333 136.0000 728.3333
#Find mean of each col
apply(h_w_i_data, 2, mean, na.rm = TRUE)
## Height Weight Income
## 66.33333 145.00000 3000.00000