143

私は のドキュメントを調べており、ここでの SO に関するいくつかの会話から、 よりも優れているはずであることにdata.tableも気づきました。rbindlistrbind

rbindlistなぜ がよりも優れているのかrbind、どのシナリオでrbindlistが実際に優れているのか知りたいrbindですか?

メモリ使用率の面で利点はありますか?

4

2 に答える 2

162

rbindlistの最適化されたバージョンでありdo.call(rbind, list(...))、使用時に遅いことで知られています。rbind.data.frame


本当に優れているところはどこですか

rbindlist輝きがどこにあるかを示すいくつかの質問

行ごとの data.frames のリストの高速ベクトル化マージ

do.call と ldply を使用して、data.frames の長いリスト (~100 万) を単一の data.frame に変換する際の問題

これらには、どれだけ速いかを示すベンチマークがあります。


rbind.data.frame が遅いのには理由があります

rbind.data.frame多くのチェックを行い、名前で一致します。(つまり、rbind.data.frame は、列の順序が異なる可能性があるという事実を考慮し、名前で照合します)、rbindlistこの種のチェックを行わず、位置で結合します

例えば

do.call(rbind, list(data.frame(a = 1:2, b = 2:3), data.frame(b = 1:2, a = 2:3)))
##    a b
## 1  1 2
## 2  2 3
## 3  2 1
## 4  3 2

rbindlist(list(data.frame(a = 1:5, b = 2:6), data.frame(b = 1:5, a = 2:6)))
##     a b
##  1: 1 2
##  2: 2 3
##  3: 1 2
##  4: 2 3

rbindlist のその他の制限事項

以前は、バグが修正されたため、に対処するのに苦労していました。factors

rbindlist 2 つの data.tables で、1 つは因子を持ち、もう 1 つは列の文字型を持ちます(バグ #2650 )

重複する列名に問題があります

警告メッセージを参照 してください: rbindlist(allargs) 内: 強制によって NA が導入されました: data.table にバグの可能性がありますか? (バグ #2384 )


rbind.data.frame の行名はイライラすることがあります

rbindlistlists data.framesとを処理できdata.tables、行名のない data.table を返します

do.call(rbind, list(...)) seeを使用して行名の混乱に陥ることができます

do.call内でrbindを使用するときに行の名前変更を回避するにはどうすればよいですか?


メモリ効率

でメモリrbindlistが実装されてCいるため、メモリ効率が高く、setattr参照によって属性を設定するために使用されます

rbind.data.frameで実装されR、多くの割り当てを行い、attr<-(andclass<-を使用し、そのrownames<-すべてが (内部的に) 作成された data.frame.

于 2013-03-28T03:16:17.583 に答える
51

によってv1.9.2rbindlistかなり進化し、次のような多くの機能が実装されました。

  • SEXPTYPEバインディング中に最上位の列を選択- FR #2456およびバグ #4981v1.9.2をクローズする際に実装されました。
  • factor列の適切な処理- 最初にバグ #2650v1.8.10のクローズで実装され、順序付けられた要素を慎重にバインドするように拡張され、 FR #4856バグ #5019がクローズされました。v1.9.2

さらに、 ではv1.9.2、R で実装された、欠落している列を埋めることによってバインドできるようにする引数rbind.data.tableも取得しました。fill

ではv1.9.3、これらの既存の機能がさらに改善されています。

  • rbindlistuse.namesデフォルトではFALSE下位互換性のための引数 を取得します。
  • rbindlistまた、引数 を取得しますfill。これは、デフォルトではFALSE下位互換性のためにも使用されます。
  • これらの機能はすべて C で実装されており、機能を追加しながら速度を落とさないように慎重に記述されています。
  • rbindlist名前で照合し、不足している列を埋めることができるようになったので、今rbind.data.tableすぐ呼び出すだけrbindlistです。唯一の違いは、下位互換性のためのuse.names=TRUEデフォルトの です。rbind.data.table

rbind.data.frame主に(Cに移行することで)回避できるコピー(@mnelも指摘)が原因で、かなり遅くなります。それだけが理由ではないと思います。列名をチェック/照合するための実装rbind.data.frameも、data.frame ごとに多数の列があり、バインドするそのような data.frame が多数ある場合に遅くなる可能性があります (以下のベンチマークに示すように)。

ただし、rbindlist特定の機能(因子レベルのチェックや名前の一致など)が欠けている(ない)ことは、rbind.data.frame. これは、C で慎重に実装され、速度とメモリが最適化されているためです。

rbindlistこれは、列名による照合とのuse.names機能 fromの使用による効率的なバインディングを強調するベンチマークですv1.9.3。データセットは、それぞれサイズが 10*500 の 10000 個の data.frames で構成されます。

dplyr注意: このベンチマークは更新され、 との比較が含まれています。bind_rows

library(data.table) # 1.11.5, 2018-06-02 00:09:06 UTC
library(dplyr) # 0.7.5.9000, 2018-06-12 01:41:40 UTC
set.seed(1L)
names = paste0("V", 1:500)
cols = 500L
foo <- function() {
    data = as.data.frame(setDT(lapply(1:cols, function(x) sample(10))))
    setnames(data, sample(names))
}
n = 10e3L
ll = vector("list", n)
for (i in 1:n) {
    .Call("Csetlistelt", ll, i, foo())
}

system.time(ans1 <- rbindlist(ll))
#  user  system elapsed 
# 1.226   0.070   1.296 

system.time(ans2 <- rbindlist(ll, use.names=TRUE))
#  user  system elapsed 
# 2.635   0.129   2.772 

system.time(ans3 <- do.call("rbind", ll))
#   user  system elapsed 
# 36.932   1.628  38.594 

system.time(ans4 <- bind_rows(ll))
#   user  system elapsed 
# 48.754   0.384  49.224 

identical(ans2, setDT(ans3)) 
# [1] TRUE
identical(ans2, setDT(ans4))
# [1] TRUE

名前をチェックせずに列をバインドするのにかかった時間はわずか 1.3 秒でしたが、列名をチェックして適切にバインドすると、さらに 1.5 秒かかりました。dplyrベース ソリューションと比較すると、これはのバージョンよりも 14 倍高速であり、18 倍高速です。

于 2014-06-01T19:32:49.963 に答える