1. ホーム
  2. r

[解決済み] data.tableで:=演算子はいつ使うべきですか?

2023-03-30 10:41:02

質問

data.table オブジェクトに:=演算子が追加されました。 この演算子は他のすべての代入演算子と何が違うのでしょうか? また、どのような用途があり、どのくらい速くなるのか、そしてどのような場合に避けるべきなのでしょうか?

どのように解決するのですか?

10分を1秒に縮める例です(NEWSより ホームページ ). これは、サブアサインされた 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 のディスパッチや引数の存在と種類のチェックなどです。 i , by , nomatch などです。つまり、内部では 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