433

ある場所で、本当に単一のビッグデータフレームに変換したいデータフレームのリストで終わるコードがあります。

私は、似ているがより複雑なことをしようとしていた以前の質問からいくつかの指針を得ました。

これが私が始めているものの例です(これは説明のために大幅に簡略化されています):

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)
4

9 に答える 9

235

dplyrパッケージbind_rows()から使用します。

bind_rows(list_of_dataframes, .id = "column_label")
于 2018-02-27T20:05:08.093 に答える
192

もう1つのオプションは、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.fillCRANの最新バージョンは次のとおりです。

> system.time({ df3 <- rbind.fill(listOfDataFrames) })
   user  system elapsed 
   0.24    0.00    0.23 
> identical(df, df3)
[1] TRUE

これはrbindよりも簡単で、わずかに高速です(これらのタイミングは複数の実行にわたって維持されます)。そして、私が理解している限り、githubのバージョンはplyrこれよりもさらに高速です。

于 2010-05-17T17:54:31.920 に答える
130

完全を期すために、この質問への回答には更新が必要だと思いました。「私は、使用do.call("rbind", ...)することがあなたが見つける最も速いアプローチになるだろうと思います...」それはおそらく2010年5月とその後しばらくの間真実でしたが、2011年9月頃に新しい機能がパッケージバージョン1.8.2rbindlistで導入されましたdata.table、「これはと同じ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
于 2013-08-28T13:49:09.230 に答える
97

バインドプロット

コード:

library(microbenchmark)

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(
plyr::rbind.fill(dflist),
dplyr::bind_rows(dflist),
data.table::rbindlist(dflist),
plyr::ldply(dflist,data.frame),
do.call("rbind",dflist),
times=1000)

ggplot2::autoplot(mb)

セッション:

R version 3.3.0 (2016-05-03)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

> packageVersion("plyr")
[1] ‘1.8.4’
> packageVersion("dplyr")
[1] ‘0.5.0’
> packageVersion("data.table")
[1] ‘1.9.6’

更新:2018年1月31日に再実行します。同じコンピューターで実行しました。パッケージの新しいバージョン。種子愛好家のための種子を追加しました。

ここに画像の説明を入力してください

set.seed(21)
library(microbenchmark)

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(
  plyr::rbind.fill(dflist),
  dplyr::bind_rows(dflist),
  data.table::rbindlist(dflist),
  plyr::ldply(dflist,data.frame),
  do.call("rbind",dflist),
  times=1000)

ggplot2::autoplot(mb)+theme_bw()


R version 3.4.0 (2017-04-21)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

> packageVersion("plyr")
[1] ‘1.8.4’
> packageVersion("dplyr")
[1] ‘0.7.2’
> packageVersion("data.table")
[1] ‘1.10.4’

更新:2019年8月6日に再実行します。

ここに画像の説明を入力してください

set.seed(21)
library(microbenchmark)

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(
  plyr::rbind.fill(dflist),
  dplyr::bind_rows(dflist),
  data.table::rbindlist(dflist),
  plyr::ldply(dflist,data.frame),
  do.call("rbind",dflist),
  purrr::map_df(dflist,dplyr::bind_rows),
  times=1000)

ggplot2::autoplot(mb)+theme_bw()

R version 3.6.0 (2019-04-26)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.2 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so

packageVersion("plyr")
packageVersion("dplyr")
packageVersion("data.table")
packageVersion("purrr")

>> packageVersion("plyr")
[1] ‘1.8.4’
>> packageVersion("dplyr")
[1] ‘0.8.3’
>> packageVersion("data.table")
[1] ‘1.12.2’
>> packageVersion("purrr")
[1] ‘0.3.2’

更新:2021年11月18日再実行。

ここに画像の説明を入力してください

set.seed(21)
library(microbenchmark)

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(
  plyr::rbind.fill(dflist),
  dplyr::bind_rows(dflist),
  data.table::rbindlist(dflist),
  plyr::ldply(dflist,data.frame),
  do.call("rbind",dflist),
  Reduce("rbind",dflist),
  purrr::map_df(dflist,dplyr::bind_rows),
  times=1000)

ggplot2::autoplot(mb)+theme_bw()

R version 4.1.2 (2021-11-01)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19043)

>packageVersion("plyr")
[1] ‘1.8.6’
> packageVersion("dplyr")
[1] ‘1.0.7’
> packageVersion("data.table")
[1] ‘1.14.2’
> packageVersion("purrr")
[1] ‘0.3.4’
于 2016-07-21T16:32:13.393 に答える
49

にもありbind_rows(x, ...)ますdplyr

> system.time({ df.Base <- do.call("rbind", listOfDataFrames) })
   user  system elapsed 
   0.08    0.00    0.07 
> 
> system.time({ df.dplyr <- as.data.frame(bind_rows(listOfDataFrames)) })
   user  system elapsed 
   0.01    0.00    0.02 
> 
> identical(df.Base, df.dplyr)
[1] TRUE
于 2015-04-29T00:32:15.930 に答える
22

これを行う別の方法があります(ループの代わりとして見落とされがちな非常に効果的な機能ツールであるため、回答に追加するだけreduceです。この特定のケースでは、どちらもdo.callよりも大幅に高速ではありません)

ベースRを使用:

df <- Reduce(rbind, listOfDataFrames)

または、tidyverseを使用して:

library(tidyverse) # or, library(dplyr); library(purrr)
df <- listOfDataFrames %>% reduce(bind_rows)
于 2017-05-17T02:26:22.023 に答える
14

整頓でそれをどのように行うべきか:

df.dplyr.purrr <- listOfDataFrames %>% map_df(bind_rows)
于 2017-05-16T13:27:19.083 に答える
12

解決策にdata.table欠けているのは、リスト内のどのデータフレームからデータが取得されているかを知るための識別子列だけです。

このようなもの:

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  
于 2017-06-22T15:30:44.343 に答える
11

最近の回答のいくつかを比較したい人のための更新されたビジュアル(私は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’
于 2017-08-22T17:04:43.120 に答える