web-dev-qa-db-ja.com

data.tableで:=演算子をいつ使用する必要がありますか?

data.tableオブジェクトに:=演算子が追加されました。この演算子が他のすべての割り当て演算子と異なるのはなぜですか?また、その用途は何ですか、どれくらい速く、いつ避けるべきですか?

87
Ari B. Friedman

次に、10分を1秒に短縮した例を示します(NEWSから homepage )。 data.frameにサブ割り当てするようなものですが、毎回テーブル全体をコピーするわけではありません。

m = matrix(1,nrow=100000,ncol=100)
DF = as.data.frame(m)
DT = as.data.table(m)

system.time(for (i in 1:1000) DF[i,1] <- i)
     user  system elapsed 
  287.062 302.627 591.984 

system.time(for (i in 1:1000) DT[i,V1:=i])
     user  system elapsed 
    1.148   0.000   1.158     ( 511 times faster )

:=jに入れると、より多くのイディオムが可能になります:

DT["a",done:=TRUE]   # binary search for group 'a' and set a flag
DT[,newcol:=42]      # add a new column by reference (no copy of existing data)
DT[,col:=NULL]       # remove a column by reference

および:

DT[,newcol:=sum(v),by=group]  # like a fast transform() by group

:=を避ける理由は考えられません! forループ内以外。 :=DT[...]内に表示されるため、[.data.tableメソッドの小さなオーバーヘッドが伴います。たとえば、S3ディスパッチ、およびibynomatchなどの引数の存在とタイプのチェック。したがって、forループ内にはオーバーヘッドが少ない:=の直接バージョンはsetと呼ばれます。詳細と例については、?setを参照してください。 setの欠点は、iが行番号(バイナリ検索なし)でなければならず、byと組み合わせられないことです。これらの制限を行うことにより、setはオーバーヘッドを劇的に削減できます。

system.time(for (i in 1:1000) set(DT,i,"V1",i))
     user  system elapsed 
    0.016   0.000   0.018
93
Matt Dowle