私は のドキュメントを調べており、ここでの SO に関するいくつかの会話から、 よりも優れているはずであることにdata.table
も気づきました。rbindlist
rbind
rbindlist
なぜ がよりも優れているのかrbind
、どのシナリオでrbindlist
が実際に優れているのか知りたいrbind
ですか?
メモリ使用率の面で利点はありますか?
私は のドキュメントを調べており、ここでの SO に関するいくつかの会話から、 よりも優れているはずであることにdata.table
も気づきました。rbindlist
rbind
rbindlist
なぜ がよりも優れているのかrbind
、どのシナリオでrbindlist
が実際に優れているのか知りたいrbind
ですか?
メモリ使用率の面で利点はありますか?
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 は、列の順序が異なる可能性があるという事実を考慮し、名前で照合します)、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
以前は、バグが修正されたため、に対処するのに苦労していました。factors
rbindlist 2 つの data.tables で、1 つは因子を持ち、もう 1 つは列の文字型を持ちます(バグ #2650 )
重複する列名に問題があります
警告メッセージを参照 してください: rbindlist(allargs) 内: 強制によって NA が導入されました: data.table にバグの可能性がありますか? (バグ #2384 )
rbindlist
lists
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.
によってv1.9.2
、rbindlist
かなり進化し、次のような多くの機能が実装されました。
さらに、 ではv1.9.2
、R で実装された、欠落している列を埋めることによってバインドできるようにする引数rbind.data.table
も取得しました。fill
ではv1.9.3
、これらの既存の機能がさらに改善されています。
rbindlist
use.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 倍高速です。