前言
R 是作为统计语言,生来就对数学有良好的支持。矩阵计算作为底层的数学工具,有非常广泛的使用场景。用R语言很好地封装了,矩阵的各种计算方法,一个函数一行代码,就能完成复杂的矩阵分解等操作。让建模人员可以更专注于模型推理和业务逻辑实现,把复杂的矩阵计算交给R语言来完成。
本文总结了 R 语言用于矩阵的各种计算操作。
1. 基本操作
# 生成矩阵
> m1:20,4,5);m
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 11 15 19
[4,] 4 8 12 16 20
# 矩阵行
> nrow(m)
[1] 4
# 矩阵列
> ncol(m)
[1] 5
取对角线元素,生成对角矩阵:
# 对角线元素
> diag(m)
[1] 1 6 11 16
# 以对角线元素,生成对角矩阵
> diag(diag(m))
[,1] [,2] [,3] [,4]
[1,] 1 0 0 0
[2,] 0 6 0 0
[3,] 0 0 11 0
上三角,下三角:
# 上三角
> m1:20,4,5)
> upper.tri(m)
[,1] [,2] [,3] [,4] [,5]
[1,] FALSE TRUE TRUE TRUE TRUE
[2,] FALSE FALSE TRUE TRUE TRUE
[3,] FALSE FALSE FALSE TRUE TRUE
[4,] FALSE FALSE FALSE FALSE TRUE
# 上三角值
> m[which(upper.tri(m))]
[1] 5 9 10 13 14 15 17 18 19 20
# 上三角矩阵
> m[!upper.tri(m)]0;m
[,1] [,2] [,3] [,4] [,5]
[1,] 0 5 9 13 17
[2,] 0 0 10 14 18
[3,] 0 0 0 15 19
[4,] 0 0 0 0 20
# 下三角矩阵
> m[!lower.tri(m)]0;m
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 2 0 0 0 0
[3,] 3 7 0 0 0
[4,] 4 8 12 0 0
矩阵转置:
> m1:20,4,5);m
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 11 15 19
[4,] 4 8 12 16 20
# 转置,行列互转
> t(m)
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
[5,] 17 18 19 20
对角矩阵填充:
# 创建方阵
> m1:16,4,4);m
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
# 用上三角填充下三角
> m[lower.tri(m)]> m
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 5 6 10 14
[3,] 9 13 11 15
[4,] 10 14 15 16
填充后,发现矩阵并不是对称的,原因是上三角取值按列取值,所以先取 10 后取 13,导致上三角和下三角取值顺序不完全一致。
> m1:16,4,4);m
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
# 上三角取值
> m[upper.tri(m)]
[1] 5 9 10 13 14 15
# 下三角取值
> m[lower.tri(m)]
[1] 2 3 4 7 8 12
调整后,我们要先转置,再取值再填充,形成对称结构。
> m1:20,4,5)
# 转置后,取下三角,填充下三角
> m[lower.tri(m)]> m
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 5 6 10 14
[3,] 9 10 11 15
[4,] 13 14 15 16
矩阵和 data.frame
转换,用行列形成索引结构。
> m1:12,4,3);m
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
# 矩阵转行列data.frame
> row1:nrow(m),ncol(m)) # 行
> col1:ncol(m),each=nrow(m)) # 列
> df# 行列索引数据框
> df
row col v
1 1 1 1
2 2 1 2
3 3 1 3
4 4 1 4
5 1 2 5
6 2 2 6
7 3 2 7
8 4 2 8
9 1 3 9
10 2 3 10
11 3 3 11
12 4 3 12
# 行列索引数据框转矩阵
> m0,length(unique(df$row)),length(unique(df$col)) )
> apply(df,1,function(dat){
+ m[dat[1],dat[2]]<3]
+ invisible()
+ })
# 打印矩阵
> m
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
2. 矩阵计算
加法,减法。
# 加载矩阵计算工具包
> library(matrixcalc)
# 新建2个矩阵,行列长度相同
> m01:20,4,5);m0
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 11 15 19
[4,] 4 8 12 16 20
> m1100,20),4,5);m1
[,1] [,2] [,3] [,4] [,5]
[1,] 40 79 97 57 78
[2,] 93 32 48 8 95
[3,] 63 6 56 12 9
[4,] 28 31 72 27 26
# 矩阵加法
> m0+m1
[,1] [,2] [,3] [,4] [,5]
[1,] 41 84 106 70 95
[2,] 95 38 58 22 113
[3,] 66 13 67 27 28
[4,] 32 39 84 43 46
# 矩阵减法
> m0-m1
[,1] [,2] [,3] [,4] [,5]
[1,] -39 -74 -88 -44 -61
[2,] -91 -26 -38 6 -77
[3,] -60 1 -45 3 10
[4,] -24 -23 -60 -11 -6
矩阵值相乘。
> m0*m1
[,1] [,2] [,3] [,4] [,5]
[1,] 40 395 873 741 1326
[2,] 186 192 480 112 1710
[3,] 189 42 616 180 171
[4,] 112 248 864 432 520
矩阵乘法,满足第二个矩阵的列数和第一个矩阵的行数相等,所以把上面生成的 m0 矩阵( 4 行 5 列)转置为( 5 行 4 列),再用 m1 矩阵( 4 行 5 列),进行矩阵乘法,得到一个 5 行 5 列的结果矩阵。
> t(m0)%*%m1
[,1] [,2] [,3] [,4] [,5]
[1,] 527 285 649 217 399
[2,] 1423 877 1741 633 1231
[3,] 2319 1469 2833 1049 2063
[4,] 3215 2061 3925 1465 2895
[5,] 4111 2653 5017 1881 3727
# 通过函数实现矩阵相乘
> crossprod(m0,m1)
[,1] [,2] [,3] [,4] [,5]
[1,] 527 285 649 217 399
[2,] 1423 877 1741 633 1231
[3,] 2319 1469 2833 1049 2063
[4,] 3215 2061 3925 1465 2895
[5,] 4111 2653 5017 1881 3727
矩阵外积。
> m1:6,2);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
> m %o% t(m) # 外积,同outer(m,t(m))
, , 1, 1
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
, , 2, 1
[,1] [,2] [,3]
[1,] 3 9 15
[2,] 6 12 18