我有一个大矩阵(2160x2160),首先我想定义一个块矩阵(比如20x20)并用0s填充对角块矩阵。我正在努力实现这一目标。
例如:
From the matrix
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 1 2 3 4 5 6 7 8 9
[2,] 11 12 13 14 15 16 17 18 19
[3,] 21 22 23 24 25 26 27 28 29
[4,] 31 32 33 34 35 36 37 38 39
[5,] 41 42 43 44 45 46 47 48 49
[6,] 51 52 53 54 55 56 57 58 59
[7,] 61 62 63 64 65 66 67 68 69
[8,] 71 72 73 74 75 76 77 78 79
[9,] 81 82 83 84 85 86 87 88 89
我首先要将块矩阵定义为3x3,然后用零填充原始矩阵的对角线块,我的示例的最终预期结果将是:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 0 0 0 4 5 6 7 8 9
[2,] 0 0 0 14 15 16 17 18 19
[3,] 0 0 0 24 25 26 27 28 29
[4,] 31 32 33 0 0 0 37 38 39
[5,] 41 42 43 0 0 0 47 48 49
[6,] 51 52 53 0 0 0 57 58 59
[7,] 61 62 63 64 65 66 0 0 0
[8,] 71 72 73 74 75 76 0 0 0
[9,] 81 82 83 84 85 86 0 0 0
我已经能够通过blockmatrix库的as.blockmatrix函数定义一个块矩阵。我想我应该打破子矩阵中的块,用0填充我需要的块然后重新构建我的原始矩阵,更改了对角线,但是我很难做到这一点。 任何其他实现这一目标的想法也是受欢迎的(在blockmatrix库的潜在解决方案之外)
我也看过bdiag函数,它包含了Matrix包,也包含了魔法下的adiag函数,但是没有想法。
提前感谢您的帮助!
答案 0 :(得分:4)
让M
成为您的矩阵,零块的大小为n x n
。然后
M[(col(M) - 1) %/% n - (row(M) - 1) %/% n == 0] <- 0
给出结果,其中%/%
表示整数除法。使用(col(M) - 1) %/% n - (row(M) - 1) %/% n
给出一个块矩阵,其中对角线上的块仅包含零。
答案 1 :(得分:3)
您可以尝试:
m <- matrix(1:(2160*2160), ncol = 2160)
block <- 20
system.time({
for(i in seq(1, nrow(m), block))
if ((block+i-1)<=nrow(m))
m[i:(block+i-1),i:(block+i-1)] <- 0
})
# time in seconds
user system elapsed
1.17 0.89 2.10
> m[1:25, 1:25]
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21] [,22] [,23] [,24] [,25]
# [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43201 45361 47521 49681 51841
# [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43202 45362 47522 49682 51842
# [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43203 45363 47523 49683 51843
# [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43204 45364 47524 49684 51844
# [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43205 45365 47525 49685 51845
# [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43206 45366 47526 49686 51846
# [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43207 45367 47527 49687 51847
# [8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43208 45368 47528 49688 51848
# [9,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43209 45369 47529 49689 51849
# [10,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43210 45370 47530 49690 51850
# [11,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43211 45371 47531 49691 51851
# [12,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43212 45372 47532 49692 51852
# [13,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43213 45373 47533 49693 51853
# [14,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43214 45374 47534 49694 51854
# [15,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43215 45375 47535 49695 51855
# [16,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43216 45376 47536 49696 51856
# [17,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43217 45377 47537 49697 51857
# [18,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43218 45378 47538 49698 51858
# [19,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43219 45379 47539 49699 51859
# [20,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43220 45380 47540 49700 51860
# [21,] 21 2181 4341 6501 8661 10821 12981 15141 17301 19461 21621 23781 25941 28101 30261 32421 34581 36741 38901 41061 0 0 0 0 0
# [22,] 22 2182 4342 6502 8662 10822 12982 15142 17302 19462 21622 23782 25942 28102 30262 32422 34582 36742 38902 41062 0 0 0 0 0
# [23,] 23 2183 4343 6503 8663 10823 12983 15143 17303 19463 21623 23783 25943 28103 30263 32423 34583 36743 38903 41063 0 0 0 0 0
# [24,] 24 2184 4344 6504 8664 10824 12984 15144 17304 19464 21624 23784 25944 28104 30264 32424 34584 36744 38904 41064 0 0 0 0 0
# [25,] 25 2185 4345 6505 8665 10825 12985 15145 17305 19465 21625 23785 25945 28105 30265 32425 34585 36745 38905 41065 0 0 0 0 0
答案 2 :(得分:2)
以下是使用矩阵子集的替代方法。
blockFill <- function(myMat, blockSize) {
# get a list of the block groups
blocks <- split(seq_len(ncol(myMat)),
rep(seq_len(ncol(myMat)), each=blockSize, length.out=ncol(myMat)))
# fill in 0s with subsetting
myMat[as.matrix(do.call(rbind, lapply(blocks, function(i) expand.grid(i, i))))] <- 0
myMat
}
这里,split
使用rep
构造块的组,每个组控制块大小和长度.out以得到矩阵的正确大小。在下一行中,lapply
在块组上执行expand.grid
,指示要操作的矩阵的元素。这些内容与rbind
和do.call
合并。
举个例子,
myMat <- matrix(1:16, 4)
blockFill(myMat, 2)
[,1] [,2] [,3] [,4]
[1,] 0 0 9 13
[2,] 0 0 10 14
[3,] 3 7 0 0
[4,] 4 8 0 0
答案 3 :(得分:2)
以下是bdiag
library(Matrix)
M*!bdiag(replicate(3, matrix(1, 3, 3), simplify = FALSE))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
# [1,] 0 0 0 4 5 6 7 8 9
# [2,] 0 0 0 14 15 16 17 18 19
# [3,] 0 0 0 24 25 26 27 28 29
# [4,] 31 32 33 0 0 0 37 38 39
# [5,] 41 42 43 0 0 0 47 48 49
# [6,] 51 52 53 0 0 0 57 58 59
# [7,] 61 62 63 64 65 66 0 0 0
# [8,] 71 72 73 74 75 76 0 0 0
# [9,] 81 82 83 84 85 86 0 0 0
M <- matrix(1:100, 10, 10, byrow=TRUE)[-10, -10]