我有代码,在一个地方以一个数据帧列表结束,我真的想转换成一个单一的大数据帧。
我从之前的一个问题中得到了一些提示,这个问题试图做一些类似但更复杂的事情。
下面是我开始的一个例子(为了说明,这是非常简化的):
listOfDataFrames <- vector(mode = "list", length = 100)
for (i in 1:100) {
listOfDataFrames[[i]] <- data.frame(a=sample(letters, 500, rep=T),
b=rnorm(500), c=rnorm(500))
}
我目前正在使用这个:
df <- do.call("rbind", listOfDataFrames)
为那些想要比较一些最近答案的人提供了一个更新的视觉效果(我想比较purrr和dplyr解决方案)。基本上我结合了@TheVTM和@rmf的答案。
代码:
library(microbenchmark)
library(data.table)
library(tidyverse)
dflist <- vector(length=10,mode="list")
for(i in 1:100)
{
dflist[[i]] <- data.frame(a=runif(n=260),b=runif(n=260),
c=rep(LETTERS,10),d=rep(LETTERS,10))
}
mb <- microbenchmark(
dplyr::bind_rows(dflist),
data.table::rbindlist(dflist),
purrr::map_df(dflist, bind_rows),
do.call("rbind",dflist),
times=500)
ggplot2::autoplot(mb)
会议信息:
sessionInfo()
R version 3.4.1 (2017-06-30)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
包版本:
> packageVersion("tidyverse")
[1] ‘1.1.1’
> packageVersion("data.table")
[1] ‘1.10.0’
另一个选择是使用plyr函数:
df <- ldply(listOfDataFrames, data.frame)
这比原来的要慢一点:
> system.time({ df <- do.call("rbind", listOfDataFrames) })
user system elapsed
0.25 0.00 0.25
> system.time({ df2 <- ldply(listOfDataFrames, data.frame) })
user system elapsed
0.30 0.00 0.29
> identical(df, df2)
[1] TRUE
我猜是用do。Call ("rbind",…)将是你能找到的最快的方法,除非你能做到(a)使用矩阵而不是data.frames, (b)预分配最终矩阵并赋值给它,而不是增长它。
编辑1:
根据Hadley的评论,下面是rbind的最新版本。从CRAN填充:
> system.time({ df3 <- rbind.fill(listOfDataFrames) })
user system elapsed
0.24 0.00 0.23
> identical(df, df3)
[1] TRUE
这比rbind更简单,并且稍微快一些(这些计时在多次运行中都有效)。据我所知,github上的plyr版本甚至比这个还要快。