Overview of linear algebra in R

Creating matrices

m <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8), nrow = 1)
n <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8), nrow = 2)
print(m)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    1    2    3    4    5    6    7    8
print(n)
     [,1] [,2] [,3] [,4]
[1,]    1    3    5    7
[2,]    2    4    6    8

Reshaping and broadcasting

m <- matrix(1:8)
print(m)
     [,1]
[1,]    1
[2,]    2
[3,]    3
[4,]    4
[5,]    5
[6,]    6
[7,]    7
[8,]    8
m <- matrix(m, nrow = 2)
print(m)
     [,1] [,2] [,3] [,4]
[1,]    1    3    5    7
[2,]    2    4    6    8
m <- matrix(m, ncol = 2)
print(m)
     [,1] [,2]
[1,]    1    5
[2,]    2    6
[3,]    3    7
[4,]    4    8
# note that R repeats things if they fit
m <- matrix(c(1, 2), ncol = 10)
print(m)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1    2    1    2    1    2    1    2    1     2

Special matrices

one <- matrix(1, nrow = 2, ncol = 3)
print(one)
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    1    1    1
zero <- matrix(0, nrow = 2, ncol = 3)
print(zero)
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
d <- diag(c(1, 2, 3, 4, 5))
print(d)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    0    0    0
[2,]    0    2    0    0    0
[3,]    0    0    3    0    0
[4,]    0    0    0    4    0
[5,]    0    0    0    0    5

Addition and scalar multiplication

x <- rnorm(4)
y <- rnorm(4)
print(x + y)
[1] -1.6008928 -0.4150518 -0.1041862 -0.2872590
# note that in R this makes sense
u <- rnorm(2)
print(x + u)
[1] -0.3343524 -0.9790628  0.5658796 -0.6296926

Element by element

u = matrix(rnorm(20), ncol = 4)
v = matrix(rnorm(20), ncol = 4)
print(u + v)
           [,1]       [,2]       [,3]        [,4]
[1,] -0.2014668 -0.6598912 -0.1189556 -1.18367458
[2,] -1.2938365  1.6027307 -0.8658610  0.35442766
[3,]  0.2359374  0.3860020 -0.4820545  1.86839898
[4,]  0.5059140  1.3892237 -3.3175182  0.03749093
[5,] -1.2269792  0.3843705  2.2109883 -0.45332415
print(u)
            [,1]       [,2]       [,3]       [,4]
[1,]  0.01594159 -0.8071523 -0.7202312 -0.8698799
[2,] -0.06590820 -0.3037873  0.2209123  1.0365347
[3,] -0.36901542  0.7328083 -0.3985388  0.3563943
[4,]  0.01834426  1.6665463 -0.4543331 -0.6770602
[5,]  0.13998513 -0.6399988  1.9793052 -0.2286634
print(1 / u)
           [,1]       [,2]       [,3]      [,4]
[1,]  62.729010 -1.2389236 -1.3884431 -1.149584
[2,] -15.172620 -3.2917771  4.5266837  0.964753
[3,]  -2.709914  1.3646133 -2.5091661  2.805881
[4,]  54.512955  0.6000433 -2.2010280 -1.476974
[5,]   7.143616 -1.5625029  0.5052278 -4.373240
print(log(abs(u)))
           [,1]       [,2]       [,3]        [,4]
[1,] -4.1388240 -0.2142429 -0.3281830 -0.13940007
[2,] -2.7194925 -1.1914276 -1.5099896  0.03588313
[3,] -0.9969168 -0.3108711 -0.9199505 -1.03171769
[4,] -3.9984384  0.5107534 -0.7889245 -0.38999515
[5,] -1.9662190 -0.4462890  0.6827459 -1.47550425

Slices using apply

u = matrix(rnorm(20), ncol = 4)
print(colMeans(u))
[1] -0.10472968 -0.46457807 -0.03911032  0.09453090
print(rowMeans(u))
[1] -0.11794402 -0.72097250  0.02731489  0.10670815  0.06253451
apply(u, 1, function(x) mean(x))
[1] -0.11794402 -0.72097250  0.02731489  0.10670815  0.06253451
apply(u, 2, function(x) var(x))
[1] 0.1747230 2.4870403 1.3972298 0.4876916

Multiplication

x <- matrix(rnorm(12), nrow = 3)
y <- matrix(rnorm(15), ncol = 3)
print(y %*% x)
          [,1]        [,2]        [,3]       [,4]
[1,] -2.974145 -0.00583667 -0.02461933  0.4582003
[2,]  1.696641  4.22131473 -2.20850618 -1.8852385
[3,]  1.287634 -3.18623006  1.59941229  1.1246493
[4,]  2.086686  3.22106962 -1.61966497 -1.6206158
[5,] -1.382868  0.46498677 -1.69590663  1.5328410

Transpose

x = matrix(rnorm(12), nrow = 3)
print(t(x))
           [,1]       [,2]       [,3]
[1,]  0.5943323  0.1133643  1.9319107
[2,] -1.3748444  1.3552909  0.4752527
[3,]  0.5430140 -0.8610553 -0.7146744
[4,]  0.9830739 -0.9319993  0.5310161
print(nrow(t(x)))
[1] 4

Norm

x = matrix(c(1, 2, 3, 4), nrow = 2)
norm(x, type = "2")
[1] 5.464986
apply(x, 2, function(x) norm(x, type = "2"))
[1] 2.236068 5.000000
apply(x, 1, function(x) norm(x, type = "2"))
[1] 3.162278 4.472136

Rank

library(Matrix)
x = matrix(c(1,2,3,4),nrow=2)
z=rankMatrix(x)
z[[1]]
[1] 2

Dataframes and arrays

Use the “[[]]” or as.vector to convert tibbles to vectors.

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.3     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.2     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ tidyr::expand() masks Matrix::expand()
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
✖ tidyr::pack()   masks Matrix::pack()
✖ tidyr::unpack() masks Matrix::unpack()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
data = read_csv("data/penguins-raw.csv")
Rows: 344 Columns: 17
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr  (9): studyName, Species, Region, Island, Stage, Individual ID, Clutch C...
dbl  (7): Sample Number, Culmen Length (mm), Culmen Depth (mm), Flipper Leng...
date (1): Date Egg

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
mass <- data |> select("Body Mass (g)")
print(mass)
# A tibble: 344 × 1
   `Body Mass (g)`
             <dbl>
 1            3750
 2            3800
 3            3250
 4              NA
 5            3450
 6            3650
 7            3625
 8            4675
 9            3475
10            4250
# ℹ 334 more rows
print(as.vector(mass))
$`Body Mass (g)`
  [1] 3750 3800 3250   NA 3450 3650 3625 4675 3475 4250 3300 3700 3200 3800 4400
 [16] 3700 3450 4500 3325 4200 3400 3600 3800 3950 3800 3800 3550 3200 3150 3950
 [31] 3250 3900 3300 3900 3325 4150 3950 3550 3300 4650 3150 3900 3100 4400 3000
 [46] 4600 3425 2975 3450 4150 3500 4300 3450 4050 2900 3700 3550 3800 2850 3750
 [61] 3150 4400 3600 4050 2850 3950 3350 4100 3050 4450 3600 3900 3550 4150 3700
 [76] 4250 3700 3900 3550 4000 3200 4700 3800 4200 3350 3550 3800 3500 3950 3600
 [91] 3550 4300 3400 4450 3300 4300 3700 4350 2900 4100 3725 4725 3075 4250 2925
[106] 3550 3750 3900 3175 4775 3825 4600 3200 4275 3900 4075 2900 3775 3350 3325
[121] 3150 3500 3450 3875 3050 4000 3275 4300 3050 4000 3325 3500 3500 4475 3425
[136] 3900 3175 3975 3400 4250 3400 3475 3050 3725 3000 3650 4250 3475 3450 3750
[151] 3700 4000 4500 5700 4450 5700 5400 4550 4800 5200 4400 5150 4650 5550 4650
[166] 5850 4200 5850 4150 6300 4800 5350 5700 5000 4400 5050 5000 5100 4100 5650
[181] 4600 5550 5250 4700 5050 6050 5150 5400 4950 5250 4350 5350 3950 5700 4300
[196] 4750 5550 4900 4200 5400 5100 5300 4850 5300 4400 5000 4900 5050 4300 5000
[211] 4450 5550 4200 5300 4400 5650 4700 5700 4650 5800 4700 5550 4750 5000 5100
[226] 5200 4700 5800 4600 6000 4750 5950 4625 5450 4725 5350 4750 5600 4600 5300
[241] 4875 5550 4950 5400 4750 5650 4850 5200 4925 4875 4625 5250 4850 5600 4975
[256] 5500 4725 5500 4700 5500 4575 5500 5000 5950 4650 5500 4375 5850 4875 6000
[271] 4925   NA 4850 5750 5200 5400 3500 3900 3650 3525 3725 3950 3250 3750 4150
[286] 3700 3800 3775 3700 4050 3575 4050 3300 3700 3450 4400 3600 3400 2900 3800
[301] 3300 4150 3400 3800 3700 4550 3200 4300 3350 4100 3600 3900 3850 4800 2700
[316] 4500 3950 3650 3550 3500 3675 4450 3400 4300 3250 3675 3325 3950 3600 4050
[331] 3350 3450 3250 4050 3800 3525 3950 3650 3650 4000 3400 3775 4100 3775

print(data[“Body Mass (g)”]) print(data[[‘Body Mass (g)’]])