如何更高效地将一个巨大的向量列表转换为矩阵?

68

我有一个长度为130,000的列表,其中每个元素都是长度为110的字符向量。我想将这个列表转换成一个大小为1,430,000*10的矩阵。如何更高效地完成此操作?\ 我的代码如下:

output=NULL
for(i in 1:length(z)) {
 output=rbind(output,
              matrix(z[[i]],ncol=10,byrow=TRUE))
}

2
如果您想要将尺寸设置为1430000*11,为什么将ncol设置为10? - Dason
1
等一下,你说每个条目有11个字符,是指它是一个具有11个项目的向量吗?我最初认为每个条目都是一个具有11个字符的字符串。你能举出z[1:2]的例子吗? - David Robinson
感谢Dason和David!那是一个打字错误。我已经纠正了它。 - user1787675
@user1787675:我还是不明白,“entry”是什么?它是一个向量吗?你能展示一下z[1:2]吗? - David Robinson
嗨,David,我查了一下词典,发现我的意思是列表中的组件。对我引起的混淆感到抱歉,我不擅长英语 :) - user1787675
5个回答

146

这段代码应该与您当前的代码等价,只是更快:

output <- matrix(unlist(z), ncol = 10, byrow = TRUE)

5
好的,翻译如下:没错。这个方法应该比我的解决方案快得多,但我想不出来这个方法,想得不够快。 - Ben Bolker
16
+1,但我建议在unlist中设置USE.NAMES=FALSE以节省时间和内存。 建议将unlist函数中的参数USE.NAMES设置为FALSE,以提高代码的运行速度并减少内存使用。 - Joshua Ulrich
10
应该使用 use.names(即小写)。 - Johan Larsson
只是为了澄清,最有效的方法应该是 output <- matrix(unlist(z), ncol = 10, byrow = TRUE, use.names=FALSE) - mikey
1
@mikey 差不多。应该是:output <- matrix(unlist(z, use.names = FALSE), ncol = 10, byrow = TRUE) - Felix

16

认为你想要的是

output <- do.call(rbind,lapply(z,matrix,ncol=10,byrow=TRUE))

即使用@BlueMagister的do.call(rbind,...)方法与lapply语句相结合,将各个列表元素转换为11*10矩阵...

基准测试结果显示,@flodel的unlist解决方案比我的解法快5倍,比原始方法快230倍...

n <- 1000
z <- replicate(n,matrix(1:110,ncol=10,byrow=TRUE),simplify=FALSE)
library(rbenchmark)
origfn <- function(z) {
    output <- NULL 
    for(i in 1:length(z))
        output<- rbind(output,matrix(z[[i]],ncol=10,byrow=TRUE))
}
rbindfn <- function(z) do.call(rbind,lapply(z,matrix,ncol=10,byrow=TRUE))
unlistfn <- function(z) matrix(unlist(z), ncol = 10, byrow = TRUE)

##          test replications elapsed relative user.self sys.self 
## 1   origfn(z)          100  36.467  230.804    34.834    1.540  
## 2  rbindfn(z)          100   0.713    4.513     0.708    0.012 
## 3 unlistfn(z)          100   0.158    1.000     0.144    0.008 

如果比例适当(即您不会遇到内存问题),完整的问题需要大约130 * 0.2秒 = 26秒在一台类似的机器上运行(我在一台两年前的MacBook Pro上完成了这个问题)。


太神奇了!在我的一年级东芝电脑上大约只需要20秒就可以完成这个操作,这为我节省了很多时间。你展示运行时间的函数也非常有趣。 - user1787675

8

如果您能提供有关输出的样本信息,将会很有帮助。不建议在越来越大的数据上递归地使用rbind。我第一个猜测可能会对您有所帮助:

z <- list(1:3,4:6,7:9)
do.call(rbind,z)

如有需要,可以查看相关问题以获得更高效的方法。


4

您还可以使用以下方法,

output <- as.matrix(as.data.frame(z))

内存使用情况与...非常相似。
output <- matrix(unlist(z), ncol = 10, byrow = TRUE)

可以使用library(pryr)中的mem_changed()来验证。

-6

您可以按如下方式使用as.matrix:

output <- as.matrix(z)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接