如何在不使用应用或循环的情况下,将矩阵的每n列插入一个列

时间:2021-02-20 20:17:10

Suppose I have a matrix

假设我有一个矩阵。

M = diag(6)

and I want to insert

我想插入

d = rep(5,6)

every 3rd column so the output is

每三列,输出是

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

output:

输出:

     [,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 个解决方案

#1


3  

We create another matrix of 5 ('m1') by more number of columns, create column index (using setdiff and seq) to replace the values in 'm1' by 'M'

我们通过更多的列创建另一个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

EDIT:

编辑:

I guess instead of creating another huge matrix, it might be memory efficient to cbind additional columns and then order the columns

我想与其创建另一个巨大的矩阵,不如使用cbind附加列,然后对列进行排序

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

Benchmarks

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

#1


3  

We create another matrix of 5 ('m1') by more number of columns, create column index (using setdiff and seq) to replace the values in 'm1' by 'M'

我们通过更多的列创建另一个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

EDIT:

编辑:

I guess instead of creating another huge matrix, it might be memory efficient to cbind additional columns and then order the columns

我想与其创建另一个巨大的矩阵,不如使用cbind附加列,然后对列进行排序

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

Benchmarks

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