如何创建对角线向量为 1 的矩阵?

问题描述 投票:0回答:4

我正在尝试创建一个具有 390 行和 2340 列的对角矩阵,但在对角线上我需要有一个向量 1,

rep(1,6)

例如,这些应该是前两行

1111110.............................0
0000001111110.......................0

我不知道该怎么做

r matrix
4个回答
9
投票

您可以轻松使用

kronecker

t(kronecker(diag(390), rep(1, 6)))

outer

+outer(1:390, rep(1:390, each = 6), `==`)

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

6
投票

你可以试试这个功能。

> 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

6
投票

根据矩阵的使用方式,稀疏矩阵可能是更好的选择:

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
© www.soinside.com 2019 - 2024. All rights reserved.