如何在矩阵中每隔n列插入一列,而不使用apply或循环。

3
假设我有一个矩阵:
M = diag(6)

and I want to insert

d = rep(5,6)

每三列输出一次。
M
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    0    0    0    0    0
[2,]    0    1    0    0    0    0
[3,]    0    0    1    0    0    0
[4,]    0    0    0    1    0    0
[5,]    0    0    0    0    1    0
[6,]    0    0    0    0    0    1
> d
[1] 5 5 5 5 5 5

输出:

     [,1] [,2] [,3] [,4]  [,5]   [,6]  [,7]   [,8]
[1,]    1    0    0    5    0       0    0      5
[2,]    0    1    0    5    0       0    0      5
[3,]    0    0    1    5    0       0    0      5
[4,]    0    0    0    5    1       0    0      5
[5,]    0    0    0    5    0       1    0      5
[6,]    0    0    0    5    0       0    1      5

1
你的矩阵有多大? - akrun
1
非常大,跨越数百万列,这个计算必须作为固定点算法的一部分进行多次执行,因此需要快速处理。 - wolfsatthedoor
如果这与您的其他问题有关,那么在拆分/堆叠过程中添加新数据是否可能?这意味着您只需要遍历矩阵一次。 - Heroka
1个回答

3
我们创建了一个更多列的5行矩阵'm1',使用'setdiff'和'seq'创建列索引,将'm1'中的值替换为'M'。
n <- 3
m1 <- matrix(5, ncol=ncol(M)+ncol(M)/n, nrow=nrow(M))
m1[,setdiff(1:ncol(m1),seq(4, ncol(m1), by=4))] <- M
m1
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#[1,]    1    0    0    5    0    0    0    5
#[2,]    0    1    0    5    0    0    0    5
#[3,]    0    0    1    5    0    0    0    5
#[4,]    0    0    0    5    1    0    0    5
#[5,]    0    0    0    5    0    1    0    5
#[6,]    0    0    0    5    0    0    1    5

编辑:

我猜想,不需要再创建一个巨大的matrix,通过cbind附加列并且order排序列可能更加节省内存。

n1 <- ncol(M)/n
M1 <- matrix(5, nrow=nrow(M), ncol=n1)
M2 <- cbind(M, M1) 
n2 <- seq(4, ncol(M2), by=4)
M3 <- M2[,order(c(setdiff(seq_len(ncol(M2)), n2), n2))]
M3
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#[1,]    1    0    0    5    0    0    0    5
#[2,]    0    1    0    5    0    0    0    5
#[3,]    0    0    1    5    0    0    0    5
#[4,]    0    0    0    5    1    0    0    5
#[5,]    0    0    0    5    0    1    0    5
#[6,]    0    0    0    5    0    0    1    5

基准测试

M <- diag(5000)
n <- 3
system.time({
n1 <- ncol(M)/n
M1 <- matrix(5, nrow=nrow(M), ncol=n1)
M2 <- cbind(M, M1) 
n2 <- seq(n+1, ncol(M2), by=n+1)
M3 <- M2[,order(c(setdiff(seq_len(ncol(M2)), n2), n2))]
})
#  user  system elapsed 
#  0.699   0.068   0.769 

n <- 3
system.time({
m1 <- matrix(5, ncol=ncol(M)+ncol(M)/n, nrow=nrow(M))
m1[,setdiff(1:ncol(m1),seq(n+1, ncol(m1), by=n+1))] <- M
})
#user  system elapsed 
#  0.722   0.061   0.785 

identical(m1, M3)
#[1] TRUE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接