我有一个由bigsplit()操作产生的列表列表(来自biganmory包的一部分biganalytics包)。如何在不使用lapply的情况下将列表列表转换为R中的稀疏矩阵?
每个列表都表示一个矩阵中的列,每个列表项都是二进制矩阵中值为1的索引。
将此列表变成稀疏二元(0/1)矩阵的最佳方法是什么? 在lapply()中使用lapply()是唯一的解决方案吗?我如何保留命名列表的因素作为列的名称?
我有一个由bigsplit()操作产生的列表列表(来自biganmory包的一部分biganalytics包)。如何在不使用lapply的情况下将列表列表转换为R中的稀疏矩阵?
每个列表都表示一个矩阵中的列,每个列表项都是二进制矩阵中值为1的索引。
将此列表变成稀疏二元(0/1)矩阵的最佳方法是什么? 在lapply()中使用lapply()是唯一的解决方案吗?我如何保留命名列表的因素作为列的名称?
您也可以考虑使用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,] . | .
以下是一些似乎适合您的描述的示例数据。
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))
如果您需要矩阵,您可以在没有任何助手的情况下执行此操作。
说你有一个像这样构成的名单:
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这很聪明很好的提醒你可以使用一维索引向量来分配(或从中提取)矩阵,填充预分配矩阵比其他方法快得多自然而然地想到涉及重复的`cbind`操作(例如使用`do.call(cbind,lapply(...))`)。 – 2011-02-09 13:50:30
使用Joris的例子,这是一个使用sapply/replace
的句法简单的方法。我怀疑Joris的方法更快,因为它填充了一个预先分配的矩阵,而我的方法隐含地涉及到一堆列,因此需要为列重复分配内存(是这样吗?)。
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
如果你有一个向量列表,你的代码会更快。返回一个错误:`错误在x [list] < - values:无效的下标类型'list'`。你必须改变c(x)到unlist(x)。 – 2011-02-09 22:42:57
要建立在里斯的答案,它使用了标索引向量来填充输出矩阵,你也可以使用一个矩阵指数矢量填补了输出矩阵;有时稍后可以更清楚地写或理解。
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)
结果是一样的。
如果你能给一些示例数据,如有可能,可运行代码的形式,这将让生活轻松许多。所以你有列表(col1 = list(1,4),col2 = list(2,6,8),类似的东西? – 2011-02-09 08:53:18
我的回复很慢,但你的回答非常好 - 谢谢!我在寻找 – Ron 2011-02-10 18:19:35