[解決済み] data.tableにキーを設定する目的は何ですか?
質問
私は
data.table
で、キーを設定する必要がある関数がたくさんあります (例:
X[Y]
). そのため、データテーブルに適切にキーを設定するために、キーが何をするのかを理解したいと思います。
私が読んだ 1 つのソースは
?setkey
.
setkey()
をソートします。data.table
で、ソート済みとマークされます。ソートされたカラムがキーとなる。キーは任意のカラムを任意の順序で指定することができる。カラムは常に昇順にソートされる。表は参照によって変更される。1列と同じ大きさの一時的なワーキングメモリ以外には、コピーは全く作成されない。
ここでの私の考えは、キーが data.table を "ソートすることで、次のような非常に似た効果をもたらすということです。
order()
. しかし、それはキーを持つ目的を説明していません。
data.tableのFAQ3.2、3.3で説明しています。
3.2 大きなテーブルでキーを持っていないのですが、それでもグループ化は本当に速いです。なぜでしょうか。
data.tableは基数ソートを使用しています。これは他の ソートアルゴリズムより明らかに高速です。基数は特に整数のみを対象としています。
?base::sort.list(x,method="radix")
. これはまたsetkey()
が速い理由の一つでもある。キーが設定されていない場合、またはキーと異なる順序でグループ化する場合 グループ化する場合、アドホック・バイと呼びます。3.3 なぜ、キーの列でグループ化する方がad hoc byより速いのですか?
各グループはRAM上で連続であるため、ページフェッチを最小限に抑えることができます。 フェッチを最小化し、メモリを一括コピーすることができるからです (
memcpy
Cでは でループさせるのではなく、一括コピーすることができるからです。
ここから推測すると、キーを設定することで、何らかの方法でRが他のアルゴリズムよりも"radix sorting"を使うことができ、そのために高速化されるのだと思います。
10分でわかるクイックスタートガイドにも、キーに関するガイドがあります。
- キーについて
まず、data.frameについて、特にrownames(英語で言うと 英語ではrow names)について考えてみましょう。つまり、1つの行に属する複数の名前です。 行に属する複数の名前です。1つの行に属する複数の名前?それは data.frameで慣れていることではありません。各行が持つ名前はせいぜい1つです。 の名前を持ちます。一人の人間は少なくとも2つの名前、rst nameとsecond nameを持っています。 これは、例えば電話帳を整理するのに便利です。 は、姓、名の順でソートされます。しかし、data.frame の各行には の各行は1つの名前しか持つことができません。
キーは1つまたは複数の 列で構成されます。 他のクラス、単に文字である必要はありません。さらに、行はキーによってソートされます。 でソートされます。したがって、data.tableは最大でも1つのキーを持つことができます。 は複数の方法でソートすることはできないからです。
一意性は強制されません。 すなわち、キーの重複は許されます。行はキーでソートされるため キーでソートされるため、キーに重複がある場合、連続して表示されます。
電話帳はキーが何であるかを理解するのに役に立ちましたが、キーは要因列を持つことと比較すると違いはないようです。さらに、なぜキーが必要なのか(特に特定の関数を使用するため)、キーとして設定する列をどのように選択するのかについては説明されていません。また、data.tableにtimeカラムがある場合、他のカラムをキーに設定すると、timeカラムも混乱してしまうようです。どなたか教えていただけませんか?
どのように解決するのですか?
この回答に加えて、ビネットを参照してください。 セカンダリインデックスとオートインデックス および キーと高速バイナリサーチベースのサブセット も同様です。
この問題 を予定している他のビネットをハイライトしています。
を踏まえて、この回答を再度更新しました(2016年2月)。
on=
機能を使用すると
アドホック
の結合も可能になります。以前の (古い) 回答は履歴を参照してください。
具体的にどのような
setkey(DT, a, b)
は何をするのでしょうか?
2つのことができます。
-
の行を並べ替えます。
data.tableの行を並べ替えます。
DT
を、提供された列によって ( a , b ) 参照により で、常に 増加する の順となる。 -
はそれらのカラムを
キー
という属性を設定することで、それらのカラムを
sorted
をDT
.
並べ替えは高速に行われます (これは データ.テーブル の内部基数ソートによる)高速で、かつ、メモリ効率も良い(1つの余分な列の型は ダブル 型が割り当てられる)。
はいつ
setkey()
は必要ですか?
グループ化操作のため。
setkey()
は決して絶対的な要件ではありませんでした。つまり、グループ化するために
コールドバイ
または
アドホック・バイ
.
## "cold" by
require(data.table)
DT <- data.table(x=rep(1:5, each=2), y=1:10)
DT[, mean(y), by=x] # no key is set, order of groups preserved in result
しかし、その前に
v1.9.6
という形式の結合は
x[i]
必須
key
に設定する必要があります。
x
.
で、新しい
on=
引数は v1.9.6+ から
で、これはもう正しくなくなり、キーを設定することは
ではなく
はここでも絶対条件ではありません。
## joins using < v1.9.6
setkey(X, a) # absolutely required
setkey(Y, a) # not absolutely required as long as 'a' is the first column
X[Y]
## joins using v1.9.6+
X[Y, on="a"]
# or if the column names are x_a and y_a respectively
X[Y, on=c("x_a" = "y_a")]
なお
on=
にも明示的に指定することができます。
keyed
の結合でも明示的に指定できます。
を必要とする唯一の操作は
key
が絶対的にセットされていなければならないのは foverlaps() 関数です。しかし、私たちはさらにいくつかの機能を開発中で、それが完成すれば、この要件はなくなります。
-
では、何のために
on=
の引数を実装する理由は何でしょうか?かなり多くの理由があります。
-
を含む操作であることを明確に区別することができる。 data.tables . ただ
X[Y]
とするだけでは、変数に適切な名前をつけることで明確になりますが、これも区別がつきません。 -
がある列を理解することもできます。 の結合/サブセット が実行されているカラムを、そのコード行を見ることですぐに理解することができます(そして、対応する
setkey()
行までトレースバックする必要はありません)。 -
カラムが追加または更新される操作において 参照によって ,
on=
の操作は、カラムを追加/更新するためだけに data.table 全体を並べ替える必要がないため、より高いパフォーマンスを発揮します。例えば## compare setkey(X, a, b) # why physically reorder X to just add/update a column? X[Y, col := i.val] ## to X[Y, col := i.val, on=c("a", "b")]
2番目のケースでは、順序を変更する必要はありませんでした。時間がかかるのは順番を計算することではなく、RAM上のdata.tableを物理的に並べ替えることであり、それを避けることで元の順番を保持し、パフォーマンスも良くなっています。
-
そうでない場合でも、繰り返しjoinを実行するのでない限りは、との間に顕著な性能差はないはずです。 キー付き と アドホック を結合します。
-
このことから、キーボードで data.table はもうないのでしょうか?
-
data.tableをキーにするメリットはありますか?
キーイングは data.table は、RAM上のこれらのカラムに基づいて物理的に順序を変更します。通常、順序を計算することは時間のかかる作業ではありません。 並べ替え そのものです。しかし、いったん RAM 上でデータをソートすると、同じグループに属する行は RAM 上ですべて連続するため、非常にキャッシュ効率がよくなります。キーが設定された data.tables の操作を高速化するのは、ソートされた状態だからです。
したがって、キャッシュ効率の良い結合/集計を行うために、data.table全体の再順序付けに費やす時間が割に合うかどうかを見極めることが重要です。通常、グループ化/結合操作を繰り返し行う場合を除き、同じ キーとなる に繰り返しグループ化/結合操作が行われない限り、顕著な差は生じないはずです。
したがって、ほとんどの場合、キーを設定する必要はもうないはずです。私たちは
on=
を使用することをお勧めします。ただし、キーを設定することでパフォーマンスが劇的に向上し、それを利用したい場合はこの限りではありません。
質問です。
と比較して、どのような性能になると思われますか?
キー付き
を使用した場合
setorder()
を並べ替えるには
データテーブル
を使用し
on=
? ここまでくれば、わかるはずです :-).
関連
-
[R] is.data.frame(x) のエラー : (リスト) オブジェクトを 'double' 型に強制できない。
-
R言語 - マトリックス
-
[解決済み] Rで文字列から文字を削除する
-
[解決済み] データフレーム列の名前によるドロップ
-
[解決済み] 情報を損なわずに因数を整数値に変換するには?
-
[解決済み] require()とlibrary()の違いは何ですか?
-
[解決済み] 統計的最頻値の求め方は?
-
[解決済み] 先頭と末尾の空白を削除するにはどうしたらよいですか?
-
[解決済み】data.table vs dplyr:一方がうまくできない、またはうまくできないことを行うことができますか?
-
[解決済み] data.frameの各行を列で指定された回数だけ繰り返す
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
R: エラー: $ 演算子は原子ベクトルに対して無効です。
-
R: hclust(d, method = method)でのエラー : 外部関数呼び出しは NA/NaN/Inf(arg10) を持つことができません。
-
R LanguageError in hist.default() : 'x' は数値でなければなりません.
-
R plot.new() のエラー : 図形の余白が大きすぎる
-
Rによる系統的クラスタリング(階層)分析のグラフ形式の完全版
-
[解決済み] Rの代入演算子"="と"<-"の違いは何ですか?
-
[解決済み] 関数のソースコードを見るにはどうしたらいいですか?
-
[解決済み] 空のdata.frameを作成する
-
[解決済み] ベクトル中のある要素のインデックスを求めるR関数はありますか?
-
[解決済み] データフレーム内の列を名前でドロップする方法