Rbind可以在R中并行化吗?

Atl*_*s1j 30 r

当我坐在这里等待一些R脚本运行...我想知道...有没有办法在R中并行化rbind?

当我处理大量数据时,我坐着等待这个电话频繁完成.

do.call("rbind", LIST)
Run Code Online (Sandbox Code Playgroud)

小智 24

到目前为止,我还没有找到一种并行方法.但是对于我的数据集(这个是大约1500个数据帧的列表,总计4.5M行),以下代码段似乎有所帮助:

while(length(lst) > 1) {
    idxlst <- seq(from=1, to=length(lst), by=2)

    lst <- lapply(idxlst, function(i) {
        if(i==length(lst)) { return(lst[[i]]) }

        return(rbind(lst[[i]], lst[[i+1]]))
    })
}
Run Code Online (Sandbox Code Playgroud)

其中lst是列表.它似乎比使用do.call(rbind, lst)或甚至do.call(rbind.fill, lst)(使用plyr包中的rbind.fill)快4倍.在每次迭代中,此代码将数据帧的数量减半.


sta*_*ant 18

因为你说你想要rbind data.frame对象你应该使用该data.table包.它有一个叫做强大rbindlist增强的功能rbind.我不是100%肯定,但我敢打赌任何使用rbind都会触发副本而rbindlist不是.无论如何a data.table是一个data.frame所以你不要尝试任何东西.

编辑:

library(data.table)
system.time(dt <- rbindlist(pieces))
utilisateur     système      écoulé 
       0.12        0.00        0.13 
tables()
     NAME  NROW MB COLS                        KEY
[1,] dt   1,000 8  X1,X2,X3,X4,X5,X6,X7,X8,...    
Total: 8MB
Run Code Online (Sandbox Code Playgroud)

闪电快......


Nic*_*bbe 16

我怀疑你可以通过平行化来让它更快地工作:除了你可能必须自己编写它的事实(第一个线程第一个和第2个项目,第二个线程第三个和第四个项目,等等它们已经完成,结果是'反弹',类似的东西 - 我没有看到非C方式改进这个),它将涉及在你的线程之间复制大量数据,这通常是事情这首先是缓慢的.

在C中,您可以在线程之间共享对象,因此您可以将所有线程写入相同的内存中.祝你好运:-)

最后,作为旁白:rbinding data.frames只是很慢.如果您事先知道所有data.frames的结构完全相同,并且它不包含纯字符列,那么您可以使用此答案中的技巧来解决我的一个问题.如果你的data.frame包含字符列,我怀疑你最好单独处理这些(do.call(c, lapply(LIST, "[[", "myCharColName")))然后用其余的处理技巧,之后你可以重新组合它们.


Xac*_*iel 7

这是一个解决方案,它自然地扩展到rbind.fill,merge和其他数据帧列表函数:

但是像我的所有答案/问题一样验证:)

require(snowfall)
require(rbenchmark)

rbinder <- function(..., cores=NULL){
  if(is.null(cores)){
    do.call("rbind", ...)
  }else{
    sequ <- as.integer(seq(1, length(...), length.out=cores+1))
    listOLists <- paste(paste("list", seq(cores), sep=""), " = ...[",  c(1, sequ[2:cores]+1), ":", sequ[2:(cores+1)], "]", sep="", collapse=", ") 
    dfs <- eval(parse(text=paste("list(", listOLists, ")")))
    suppressMessages(sfInit(parallel=TRUE, cores))
    dfs <- sfLapply(dfs, function(x) do.call("rbind", x))
    suppressMessages(sfStop())
    do.call("rbind", dfs)   
  }
}

pieces <- lapply(seq(1000), function(.) data.frame(matrix(runif(1000), ncol=1000)))

benchmark(do.call("rbind", pieces), rbinder(pieces), rbinder(pieces, cores=4), replications = 10)

#test replications elapsed relative user.self sys.self user.child sys.child
#With intel i5 3570k    
#1     do.call("rbind", pieces)           10  116.70    6.505    115.79     0.10         NA        NA
#3 rbinder(pieces, cores = 4)           10   17.94    1.000      1.67     2.12         NA        NA
#2              rbinder(pieces)           10  116.03    6.468    115.50     0.05         NA        NA
Run Code Online (Sandbox Code Playgroud)