## What is a Matrix?

A matrix is a collection of elements, all the same type, arranged in a two-dimensional layout.

In a nutshell, a matrix is just a vector that has two dimensions.

When using R, you will frequently encounter the four basic matrix types viz. logical, character, integer and double (often called numeric).

## Create a Matrix

You can create a matrix using the `matrix()` function and specifying the data and the number of rows and columns to make the matrix.

``````# Create a numeric matrix
m <- matrix(1:6, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
``````

Matrix can contain character values as well.

``````# Create a character matrix
letters <- c("a","b","c","d","e","f")
m <- matrix(letters, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,] "a"  "c"  "e"
[2,] "b"  "d"  "f"
``````

You don’t have to specify both ncol and nrow. If you specify one, R will know automatically what the other needs to be.

``````m <- matrix(1:6, nrow=2)
m
[,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
``````

By default, the matrix is filled column-by-column. By setting `byrow=TRUE` you can fill the matrix row-by-row.

``````m <- matrix(1:6, nrow=2, ncol=3, byrow=TRUE)
m
[,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
``````

## Combine Vectors into a Matrix

You can also create a matrix using the `cbind()` and `rbind()` functions. However, keep in mind that the vectors that are being binded must be of equal length and same type.

``````v1 <- c(1, 2, 3)
v2 <- c(4, 5, 6)
v3 <- c(7, 8, 9)

rbind(v1, v2, v3)
[,1] [,2] [,3]
v1    1    2    3
v2    4    5    6
v3    7    8    9
``````

The `cbind()` function does something similar. It binds the vectors as columns of a matrix.

``````v1 <- c(1, 2, 3)
v2 <- c(4, 5, 6)
v3 <- c(7, 8, 9)

cbind(v1, v2, v3)
v1 v2 v3
[1,]  1  4  7
[2,]  2  5  8
[3,]  3  6  9
``````

## Change Matrix Dimension

By using the `dim()` function you can get the dimension of the matrix without looking at the structure.

``````# Print the dimension of a matrix
m <- matrix(1:6, nrow=2, ncol=3)
dim(m)
[1] 2 3
``````

The `dim()` function can also be used to set the dimension of the matrix.

``````# Change the dimension of a matrix

# define a 2x3 matrix
m <- matrix(1:6, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

# make it 3x2
dim(m) <- c(3,2)
m
[,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

# make it 1x6
dim(m) <- c(1,6)
m
[,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    2    3    4    5    6
``````

## Naming Matrix Rows and Columns

R lets you assign descriptive names to the rows and columns of a matrix. It is useful for subsetting and printing the matrix.

You can do this by assigning two element list containing row and column names to the dimnames attribute.

``````# Assign names to the rows and columns
m <- matrix(1:6, nrow=2, ncol=3)
dimnames(m) <- list(c("r1","r2"), c("c1","c2","c3"))
m
c1 c2 c3
r1  1  3  5
r2  2  4  6
``````

You can even name the rows and columns while creating a matrix by passing dimnames argument.

``````# Naming rows and columns while matrix creation
m <- matrix(1:6, nrow=2, ncol=3, dimnames=list(c("r1","r2"), c("c1","c2","c3")))
m
c1 c2 c3
r1  1  3  5
r2  2  4  6
``````

By using the `rownames()` and `colnames()` function you can assign row names and column names separately.

``````# Assign names to the rows and columns separately
m <- matrix(1:6, nrow=2, ncol=3)
rownames(m) <- c("r1","r2")
colnames(m) <- c("c1","c2","c3")
m
c1 c2 c3
r1  1  3  5
r2  2  4  6
``````

You can use the same `dimnames()`, `colnames()` and `rownames()` functions to print column names and row names.

``````# print column names
colnames(m)
[1] "c1" "c2" "c3"

# print row names
rownames(m)
[1] "r1" "r2"

# print both
dimnames(m)
[[1]]
[1] "r1" "r2"

[[2]]
[1] "c1" "c2" "c3"
``````

## Subsetting Matrices

In R, subsetting elements from matrices is much like subsetting elements from vectors.

The only difference is that you now have to specify both the row and the column position, in the order of `[row, column]`.

### Subsetting by Positive Integer

Subsetting with positive integers returns the elements at the specified positions.

``````m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

# subset for 2nd row
m[2,]
[1] 2 5 8

# subset for 3rd column
m[,3]
[1] 7 8 9

# select single element
m[2,3]
[1] 8

# subset for row 1 and 2 but keep all columns
m[1:2,]
[,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8

# subset for both rows and columns
m[1:2,2:3]
[,1] [,2]
[1,]    4    7
[2,]    5    8

# use a vector to subset
m[1:2,c(1, 3)]
[,1] [,2]
[1,]    1    7
[2,]    2    8
``````

When you subset for a single row or a column, the result will always be a vector. To avoid this you can set the drop argument to FALSE.

``````m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

# simplifies the output to a vector
m[, 2]
[1] 4 5 6
class(m[, 2])
[1] "integer"

# preserves output as a matrix
m[, 2, drop = FALSE]
[,1]
[1,]    4
[2,]    5
[3,]    6
class(m[, 2, drop = FALSE])
[1] "matrix"
``````

### Subsetting by Negative Integer

Subsetting with negative integers will omit the elements at the specified positions.

``````m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

# omit 2nd row
m[-2,]
[,1] [,2] [,3]
[1,]    1    4    7
[2,]    3    6    9

# omit 3rd column
m[,-3]
[,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

# omit 2nd row and 3rd column
m[-2,-3]
[,1] [,2]
[1,]    1    4
[2,]    3    6
``````

### Subsetting by Logical Values

Subsetting with logical values will return the elements where the corresponding logical value is TRUE.

``````m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

# select elements where corresponding logical value is TRUE
m[c(TRUE,FALSE,TRUE),c(TRUE,TRUE,FALSE)]
[,1] [,2]
[1,]    1    4
[2,]    3    6

# select elements greater than 5
m[m > 5]
[1] 6 7 8 9

# select even elements
m[m %% 2 == 0]
[1] 2 4 6 8
``````

### Subsetting by Names

Subsetting with names will return the elements having the matching names.

``````m <- matrix(1:9, nrow=3, ncol=3)
dimnames(m) <- list(c("r1","r2","r3"), c("c1","c2","c3"))

# subset for 2nd row
m["r2",]
c1 c2 c3
2  5  8

# subset for 3rd column
m[,"c3"]
r1 r2 r3
7  8  9

# subset for 1st and 3rd row but keep all columns
m[c("r1","r3"),]
c1 c2 c3
r1  1  4  7
r3  3  6  9

# select single element
m["r2","c3"]
[1] 8
``````

## Add New Rows and Columns to Matrix

You can use the `cbind()` and `rbind()` functions for adding new rows and columns to the matrix as well. However, keep in mind that the vectors that are being added must be of equal length and same type.

``````m <- matrix(1:6, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

cbind(m, c(7,8))
[,1] [,2] [,3] [,4]
[1,]    1    3    5    7
[2,]    2    4    6    8

rbind(m, c(10,20,30))
[,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
[3,]   10   20   30
``````

## Modify Matrix Elements

Modifying a matrix element is pretty straightforward. Access the element using `[]` operator and simply assign a new value.

``````m <- matrix(1:6, nrow=2, ncol=3)

# moidfy single element
m[1,2] <- 99
m
[,1] [,2] [,3]
[1,]    1   99    5
[2,]    2    4    6

# modify 2nd row
m[2,] <- c(10,20,30)
m
[,1] [,2] [,3]
[1,]    1   99    5
[2,]   10   20   30

# modify elements less than 5
m[m > 5] <- 0
m
[,1] [,2] [,3]
[1,]    1    0    5
[2,]    0    0    0
``````

## Matrix Operations

The most powerful feature of R is the ease of dealing with matrix operations. Because much of statistics depend on matrix operations, R perform them in an easy and optimized way:

• Matrix transpose
• Creating an identity matrix
• Scalar multiple of a matrix
• Matrix multiplication
• Matrix inversion

### Matrix Transpose

The transpose of a matrix is simply a flipped version of the original matrix obtained by switching rows with columns. To transpose a matrix, use `t()` function.

``````m <- matrix(1:6, nrow=2, ncol=3)
m
[,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
t(m)
[,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    5    6
``````

### Creating an Identity Matrix

You can create an identity matrix using the `diag()` function. Its behavior depends on what argument you pass.

If you pass a single positive integer, then `diag()` will create an identity matrix of that dimension.

``````# Create a 3x3 identity matrix
diag(3)
[,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    1    0
[3,]    0    0    1
``````

If you pass a matrix, `diag()` will return the diagonal elements of the matrix.

``````# Return diagonal elements of the matrix
m <- matrix(1:9, nrow=3, ncol=3)
m
[,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
diag(m)
[1] 1 5 9
``````

### Scalar Multiple of a Matrix

When you multiply a matrix by a scalar value (a single number), every individual element is multiplied by that value.

``````# Multiply each matrix element by 10
m <- matrix(1:6, nrow=2, ncol=3)
m * 10
[,1] [,2] [,3]
[1,]   10   30   50
[2,]   20   40   60
``````

R performs addition or subtraction of two matrices of equal size in an element-wise manner. Meaning, corresponding elements are added or subtracted from one another, depending on the operation.

``````m1 <- matrix(1:6, nrow=2, ncol=3)
m1
[,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

m2 <- matrix(-6:-1, nrow=2, ncol=3)
m2
[,1] [,2] [,3]
[1,]   -6   -4   -2
[2,]   -5   -3   -1

m1 + m2
[,1] [,2] [,3]
[1,]   -5   -1    3
[2,]   -3    1    5

# subtraction
m1 - m2
[,1] [,2] [,3]
[1,]    7    7    7
[2,]    7    7    7
``````

### Matrix Multiplication

Unlike scalar multiplication, matrix multiplication is not a simple element-by-element calculation, and the standard `*` operator cannot be used. Instead, you must use R’s matrix product operator `%*%`.

``````m1 <- matrix(1:6, nrow=2, ncol=3)
m1
[,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

m2 <- matrix(1:6, nrow=3, ncol=2)
m2
[,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

# multiplication
m1 %*% m2
[,1] [,2]
[1,]   22   49
[2,]   28   64
``````

### Matrix Inversion

The inverse of a matrix can be calculated by using the `solve()` function.

``````m <- matrix(1:4, nrow=2, ncol=2)
m
[,1] [,2]
[1,]    1    3
[2,]    2    4

solve(m)
[,1] [,2]
[1,]   -2  1.5
[2,]    1 -0.5
``````

## Matrix Length

You can find the total number of values in a matrix using the `length()` function.

``````m <- matrix(1:6, nrow=2, ncol=3)
length(m)
[1] 6
``````