r-如何有效地在(稀疏)矩阵中插入行



我有一个巨大的稀疏矩阵,需要在特定的行索引处插入一行。我基本上应用了这里建议的技术,但这是非常低效的,因为它复制了原始矩阵。

简而言之,这是代码,其范围是有效地生成M2(理想情况下,直接替换M,这样甚至不需要M2(:

library(Matrix)
M  = as(cbind(1:4,1:4),"sparseMatrix") # original sparse matrix
M # view
v  = c(2,4) # row indices where new rows should be inserted
M2 = M # copy matrix to keep sparse class
for(i in 1:length(v)) M2 = rbind(M2,rep(0, ncol(M2))) # insert new rows at end
M2[-v,] = M # get each row in v 2 times ## <- THIS takes very long
M2[v,] = 0 # populate the newly inserted rows (e.g. here: 0)
M2 # view

理想情况下,我正在寻找一个函数,例如向量的append或tibble的add_row

编辑:我注意到上面的过程不仅效率低下,而且不是我想要的,因为它在(结果(矩阵M2的索引2和4处添加了行,而我正在寻找在矩阵(初始(的索引2或4处添加行,即到目前为止的最终结果是:

[1,] 1 1
[2,] . .
[3,] 2 2
[4,] . .
[5,] 3 3
[6,] 4 4

即在新矩阵的索引2和4处添加行。我要找的是:

[1,] 1 1
[2,] . .
[3,] 2 2
[4,] 3 3
[5,] . .
[6,] 4 4

即在旧矩阵的索引2和4之前已经添加了新行。在他的+1回答中,@Ben Bolker正确地解释了这一点。:(

我认为这应该相当有效:它以稀疏(dgCMatrixdgTMatrix(格式处理矩阵的底层行索引和维度。

add_rows <- function(M,v) {
oldind <- seq(dim(M)[1])-1L   ## all rows (0-indexed)
## new row indices: count how many rows are inserted before a given row
## (maybe a clearer/better/more efficient way to do this?)
newind <- oldind + as.integer(rowSums(outer(oldind,v,">=")))
## modify dimensions
M@Dim <- M@Dim + c(length(v),0L)
## modify row indices (1L accounts for 0 vs 1-indexing)
M@i <- newind[M@i+1L]
M
}

最有可能成为(内存/计算(瓶颈的部分是新行索引的计算。我通过构建所有行号的索引来实现这一点。以下版本仅对占用的行执行newind计算,代价是额外调用unique()match()

add_rows_2 <- function(M,v) {
oldind <- unique(M@i)
## new row indices
newind <- oldind + as.integer(rowSums(outer(oldind,v,">=")))
## modify dimensions
M@Dim <- M@Dim + c(length(v),0L)
M@i <- newind[match(M@i,oldind)]
M
}

最新更新