我有代码,在一个地方以一个数据帧列表结束,我真的想转换成一个单一的大数据帧。

我从之前的一个问题中得到了一些提示,这个问题试图做一些类似但更复杂的事情。

下面是我开始的一个例子(为了说明,这是非常简化的):

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)

当前回答

在tidyverse中应该如何做:

df.dplyr.purrr <- listOfDataFrames %>% map_df(bind_rows)

其他回答

为了完整起见,我认为这个问题的答案需要更新。“我猜是用do。Call ("rbind",…)将是你能找到的最快的方法。"2010年5月和之后的一段时间可能是这样,但在2011年9月左右,数据中引入了一个新函数rbindlist。表包版本1.8.2,与注释“这是相同的do.call("rbind",l),但更快”。快了多少?

library(rbenchmark)
benchmark(
  do.call = do.call("rbind", listOfDataFrames),
  plyr_rbind.fill = plyr::rbind.fill(listOfDataFrames), 
  plyr_ldply = plyr::ldply(listOfDataFrames, data.frame),
  data.table_rbindlist = as.data.frame(data.table::rbindlist(listOfDataFrames)),
  replications = 100, order = "relative", 
  columns=c('test','replications', 'elapsed','relative')
  ) 

                  test replications elapsed relative
4 data.table_rbindlist          100    0.11    1.000
1              do.call          100    9.39   85.364
2      plyr_rbind.fill          100   12.08  109.818
3           plyr_ldply          100   15.14  137.636

在tidyverse中应该如何做:

df.dplyr.purrr <- listOfDataFrames %>% map_df(bind_rows)

唯一的方法就是用数据来解决问题。表中缺少的是标识符列,以知道数据来自列表中的哪个数据帧。

就像这样:

df_id <- data.table::rbindlist(listOfDataFrames, idcol = TRUE)

idcol参数添加一个列(.id),标识列表中包含的数据帧的来源。结果是这样的:

.id a         b           c
1   u   -0.05315128 -1.31975849 
1   b   -1.00404849 1.15257952  
1   y   1.17478229  -0.91043925 
1   q   -1.65488899 0.05846295  
1   c   -1.43730524 0.95245909  
1   b   0.56434313  0.93813197  

使用dplyr包中的bind_rows():

bind_rows(list_of_dataframes, .id = "column_label")

这里有另一种方法可以做到这一点(只是将它添加到答案中,因为reduce是一个非常有效的功能工具,它经常被忽视为循环的替代品。在这个特定的情况下,这两种方法都没有比do.call快得多)

使用底数R:

df <- Reduce(rbind, listOfDataFrames)

或者,用tidyverse来形容:

library(tidyverse) # or, library(dplyr); library(purrr)
df <- listOfDataFrames %>% reduce(bind_rows)