如何在不使用lapply的情况下将列表列表转换为R中的稀疏矩阵?

时间:2011-02-09 07:36:29

标签: r sparse-matrix

我有一个bigsplit()操作列表(来自biganalytics包,bigmemory包的一部分)。

每个列表代表一个矩阵中的列,每个列表项是二进制矩阵中值为1的索引。

将此列表转换为稀疏二进制(0/1)矩阵的最佳方法是什么? 在lapply()中使用lapply()是唯一的解决方案吗?如何将列表命名为列的名称?

5 个答案:

答案 0 :(得分:5)

如果你需要一个矩阵,你可以在没有任何屈服的情况下做到这一点。

假设你有一个像这样构建的列表:

Test <- list(
    col1=list(2,4,7),
    col2=list(3,2,6,8),
    col3=list(1,4,5,3,7)
)

首先,构造一个具有正确尺寸的零的矩阵。如果您事先了解它们,那很容易。否则你可以很容易地得出:

n.cols <- length(Test)
n.ids <- sapply(Test,length)
n.rows <- max(unlist(Test))
out <- matrix(0,nrow=n.rows,ncol=n.cols)

然后你使用矩阵按列填充的事实来计算必须成为一个的每个单元格的索引:

id <- unlist(Test)+rep(0:(n.cols-1),n.ids)*n.rows
out[id] <- 1
colnames(out) <- names(Test)

这给出了:

> out
     col1 col2 col3
[1,]    0    0    1
[2,]    1    1    0
[3,]    0    1    1
[4,]    1    0    1
[5,]    0    0    1
[6,]    0    1    0
[7,]    1    0    1
[8,]    0    1    0

答案 1 :(得分:2)

使用Joris的例子,这是一种使用sapply/replace的语法简单方法。我怀疑Joris的方法更快,因为它填充了预先分配的矩阵,而我的方法隐含地涉及cbind一堆列,因此需要重复的列分配(这是真的吗?)

Test <- list( 
col1=list(2,4,7), 
col2=list(3,2,6,8), 
col3=list(1,4,5,3,7) 
) 

> z <- rep(0, max(unlist(Test)))
> sapply( Test, function(x) replace(z,unlist(x),1))
     col1 col2 col3
[1,]    0    0    1
[2,]    1    1    0
[3,]    0    1    1
[4,]    1    0    1
[5,]    0    0    1
[6,]    0    1    0
[7,]    1    0    1
[8,]    0    1    0

答案 2 :(得分:2)

你也可以考虑使用Matrix包来处理大型稀疏矩阵,它比基本R更有效。你可以通过描述哪些行和列应该是1来构建一个0和1的稀疏矩阵。

library(Matrix)
Test <- list(
    col1=list(2,4,7),
    col2=list(3,2,6,8),
    col3=list(1,4,5,3,7)
)
n.ids <- sapply(Test,length)
vals <- unlist(Test)
out <- sparseMatrix(vals, rep(seq_along(n.ids), n.ids))

结果是

> out
8 x 3 sparse Matrix of class "ngCMatrix"

[1,] . . |
[2,] | | .
[3,] . | |
[4,] | . |
[5,] . . |
[6,] . | .
[7,] | . |
[8,] . | .

答案 3 :(得分:0)

以下是一些似乎符合您描述的示例数据。

a <- as.list(sample(20, 5))
b <- as.list(sample(20, 5))
c <- as.list(sample(20, 5))
abc <- list(a = a, b = b, c = c)

我没有看到使用嵌套lapply()的方法,但这是另一种方法。消除unlist()会很好,但也许其他人可以改进这一点。

sp_to_bin <- function(splist) {
  binlist <- numeric(100)
  binlist[unlist(splist)] <- 1
  return(binlist)
}
bindf <- data.frame(lapply(abc, sp_to_bin))

答案 4 :(得分:0)

基于Joris的答案,使用标量索引向量填充输出矩阵,您还可以使用矩阵索引向量来填充输出矩阵;以后写这个或者理解的时候有点清楚。

Test <- list(
    col1=list(2,4,7),
    col2=list(3,2,6,8),
    col3=list(1,4,5,3,7)
)

n.cols <- length(Test)
n.ids <- sapply(Test,length)
vals <- unlist(Test)
n.rows <- max(vals)
idx <- cbind(vals, rep(seq_along(n.ids), n.ids))
out <- matrix(0,nrow=n.rows,ncol=n.cols)
out[idx] <- 1
colnames(out) <- names(Test)

结果是一样的。