我正在尝试创建一个具有 390 行和 2340 列的对角矩阵,但在对角线上我需要有一个向量 1,
rep(1,6)
。
例如,这些应该是前两行
1111110.............................0
0000001111110.......................0
我不知道该怎么做
您可以轻松使用
kronecker
t(kronecker(diag(390), rep(1, 6)))
或
outer
+outer(1:390, rep(1:390, each = 6), `==`)
逐行思考,您需要六个 1,然后是 2340 个零(其中六个溢出到下一行,将 1 的序列移动六列),一遍又一遍地重复。所以你可以通过这样做来实现这一点:
matrix(c(rep(1, 6), rep(0, 2340)), ncol = 2340, nrow = 390, byrow = TRUE)
请注意,将会出现关于数据不是行数倍数的警告,但这是预期的:最后一行上的零将分配给第 391 行,但我们说我们只需要 390,因此数据得到被截断了。
您可以通过以下方式验证结果:
x[1:20, 1:20] # Top-left corner
x[371:390, 2321:2340] # Bottom-right corner
你可以试试这个功能。
> fn <- \(len_1, m) {
+ t(sapply(0:(m - 1), \(i)
+ c(rep_len(0, len_1*i),
+ rep_len(1, len_1),
+ rep_len(0, len_1*(m - i - 1)))))
+ }
>
> fn(1, 3)
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
> fn(2, 4)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 1 0 0 0 0 0 0
[2,] 0 0 1 1 0 0 0 0
[3,] 0 0 0 0 1 1 0 0
[4,] 0 0 0 0 0 0 1 1
> fn(3, 2)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 0 0 0
[2,] 0 0 0 1 1 1
根据矩阵的使用方式,稀疏矩阵可能是更好的选择:
library(Matrix)
x <- sparseMatrix(rep(1:390, each = 6), 1:2340)
检查
x[1:3, 1:18] # top left
#> 3 x 18 sparse Matrix of class "ngCMatrix"
#>
#> [1,] | | | | | | . . . . . . . . . . . .
#> [2,] . . . . . . | | | | | | . . . . . .
#> [3,] . . . . . . . . . . . . | | | | | |
x[388:390, 2323:2340] # bottom right
#> 3 x 18 sparse Matrix of class "ngCMatrix"
#>
#> [1,] | | | | | | . . . . . . . . . . . .
#> [2,] . . . . . . | | | | | | . . . . . .
#> [3,] . . . . . . . . . . . . | | | | | |
与密集
matrix
对象相比,稀疏矩阵使用的内存少 180 倍,构建速度更快,并且在许多情况下会加快操作速度。示范:
m <- matrix(rep(1:0, c(6, 2340)), 390, 2340, 1)
object.size(m)
#> 3650616 bytes
object.size(x)
#> 20064 bytes
microbenchmark::microbenchmark(
dense = matrix(rep(1:0, c(6, 2340)), 390, 2340, 1),
sparse = sparseMatrix(rep(1:390, each = 6), 1:2340)
)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> dense 2176.6 2331.3 3025.947 2510.55 2692.2 12528.5 100
#> sparse 344.3 374.9 546.522 440.85 493.3 10121.5 100
y <- matrix(runif(390*2340), 390, 2340)
microbenchmark::microbenchmark(
dense = crossprod(m, y),
sparse = as.matrix(crossprod(x, y)),
check = "equal",
times = 10,
unit = "relative"
)
#> Unit: relative
#> expr min lq mean median uq max neval
#> dense 121.5391 111.6669 77.11411 82.2131 60.29327 51.23242 10
#> sparse 1.0000 1.0000 1.00000 1.0000 1.00000 1.00000 10