通过稀疏矩阵中非零条目的行索引复制这些条目的值

时间:2018-07-05 17:16:23

标签: r matrix sparse-matrix

给定一个大型的稀疏整数矩阵,我想要一个列表,其中列表中的每个元素都是一个包含对应行中非零元素索引的向量,用指定的次数进行复制按元素。矩阵很大,所以我需要一个可扩展的解决方案。

这是一个工作代码非常慢的示例。

sparse_matrix <- matrix(c(1, 0, 0, 0, 2, 0, 1, 5, 0, 0, 0, 0), nrow = 2)
#       [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    1    0    2    1    0    0
#[2,]    0    0    0    5    0    0


# A very slow attempt that gives the right answer
lapply(seq_len(nrow(sparse_matrix)), function(r) {
  rep(seq_len(ncol(sparse_matrix)), sparse_matrix[r,])
}     )

#[[1]]
#[1] 1 3 3 4
#
#[[2]]
#[1] 4 4 4 4 4

编辑:我意识到我在原始帖子中未正确说明我的问题-道歉。请参考上面的示例。

编辑2:为一个用例确定两种解决方案的时间:

sparse_matrix <- rsparsematrix (1E4,1E3, 0.01,rand.x = function(n) 1 + round(abs(rnorm(n))))
sparse_matrix <- as.matrix(sparse_matrix)

# 李哲源
ptm <- proc.time()
spM <- as(sparse_matrix, "dgRMatrix")
RowNumber <- rep(1:nrow(spM), diff(spM@p))
ColInd <- split(spM@j + 1, RowNumber)
nze <- split(spM@x, RowNumber)
output <- mapply(rep, ColInd, nze)  
print(proc.time() - ptm)
# 0.232 seconds

#akrun
ptm <- proc.time()
v1 <- c(col(sparse_matrix) * !! sparse_matrix)
v1 <-  setNames(v1, t(row(sparse_matrix)))
output <- rep(v1, sparse_matrix)
print(proc.time() - ptm)
# 1.8 seconds

2 个答案:

答案 0 :(得分:3)

您是否熟悉稀疏矩阵的压缩行存储?您想要的索引只是这种存储中的关键组成部分。 R软件包Matrix为此具有其“ dgRMatrix”类。

library(Matrix)
spM <- as(sparse_matrix, "dgRMatrix")
## which row do those non-zero entries lie?
RowNumber <- rep(1:nrow(spM), diff(spM@p))
## position index of those entries on each row, i.e., column index
ColInd <- split(spM@j + 1, RowNumber)
## none-zero-element on each row
nze <- split(spM@x, RowNumber)
## expand position index by matrix value
mapply(rep, ColInd, nze)

#$`1`
#[1] 1 3 3 4

#$`2`
#[1] 4 4 4 4 4

  

如果矩阵存储为“ dgCMatrix”,是否可以将其转换为“ dgRMatrix”?在这种情况下,第一行给出:没有将'dgCMatrix'强制为dgRMatrix'的方法或默认值

这不是从“ dgCMatrix”到“ dgRMatrix”的强制方法。 sparse_matrix与您的帖子一样密集。因此,as背后的强制是从“矩阵”到“ dgRMatrix”。

但是,如果您已经将其作为“ dgCMatrix”,则可以先对其进行转置,然后在此“ dgCMatrix”上执行类似的操作。见下文。

spM <- as(sparse_matrix, "dgCMatrix")
## transpose
spM <- t(spM)
## which column do those non-zero entries lie?
ColNumber <- rep(1:ncol(spM), diff(spM@p))
## position index of those entries on each column, i.e., row index
RowInd <- split(spM@i + 1, ColNumber)
## none-zero-element on each column
nze <- split(spM@x, ColNumber)
## expand position index by matrix value
mapply(rep, RowInd, nze)

#$`1`
#[1] 1 3 3 4

#$`2`
#[1] 4 4 4 4 4

感谢user20650的(大)进步。

对于带有“ dgRMatrix”的第一种情况,

spM <- as(sparse_matrix, "dgRMatrix")
RowNumber <- rep(1:nrow(spM), diff(spM@p))
split(rep(spM@j + 1, spM@x), rep(RowNumber, spM@x))

对于带有“ dgCMatrix”的第二种情况

spM <- as(sparse_matrix, "dgCMatrix")
ColInd <- rep(1:ncol(spM), diff(spM@p))
split(rep(ColInd, spM@x), rep(spM@i, spM@x))

答案 1 :(得分:2)

我们可以将whicharr.ind一起使用,以获取matrix中的行和列索引

which(sparse_matrix !=0, arr.ind = TRUE) 

第二种情况

rep(col(sparse_matrix) * !! sparse_matrix, sparse_matrix)

给出一个vector,但是如果需要一个标识符,则创建一个named向量

v1 <- c(col(sparse_matrix) * !! sparse_matrix)
v1 <-  setNames(v1, t(row(sparse_matrix)))
rep(v1, sparse_matrix)
#1 1 1 2 2 2 2 2 2 
#1 3 3 4 4 4 4 4 4