19

私が本当に気に入ってdata.tableいるのは、:=コストのかかるコピーを必要とせずに、参照によってテーブルを変更するイディオムです。私が理解していることから、これはdata.table他の方法と比較して非常に高速になる側面の1つです。

dplyrさて、同じようにパフォーマンスが高いと思われるパッケージをいじり始めました。しかし、<-演算子を使用して結果を割り当てる必要があるため、このレベルではパフォーマンスが低下すると予想していました。ただし、ないようです。

例として:

library(dplyr)
library(Lahman)
library(microbenchmark)
library(ggplot2)

df <- Batting[ c("yearID", "teamID", "G_batting") ]

mb <- microbenchmark(
  dplyr = {
    tb <- tbl_df( df )
    tb <- tb %.%
      group_by( yearID, teamID ) %.%
      mutate( G_batting = max(G_batting) )
  },
  data.table = {
    dt <- as.data.table( df )
    dt[ , G_batting := max(G_batting), by = list( yearID, teamID ) ]
  },
  times = 500
)

qplot( data = mb, x = expr, y = time * 1E-6, geom = "boxplot", ylab="time [ms]", xlab = "approach" )

ここに画像の説明を入力

どうすればこれが可能になるのだろうか?または、ベンチマークの方法に概念上の誤りがありますか? 私の理解は<-間違っていますか?

4

2 に答える 2

11

何が起こっているのかを理解するには、正確に何がコピーされているのかを理解する必要があります。データ フレームは、基本的に列へのポインターの配列にすぎないため、実際にはコピーするのは非常に安価です。これらのポインターをコピーするだけでよいため、データフレームの浅いコピーを行うのは非常に安価です。

ただし、ほとんどの基本 R 関数はディープ コピーを実行します。だからあなたがするとき:

df <- data.frame(x = 1:10, y = 1:10)
transform(df, z = x + y)

R はデータ フレームをコピーするだけでなく、個々の列を実際にコピーします。dplyr は、changes()これをより見やすくする機能を提供します。データ フレームの列ごとに、その列が存在するメモリの場所が表示されます。変更されている場合は、列全体がコピーされています。

df2 <- transform(df, z = x + y)
changes(df, df2)
#> Changed variables:
#>           old            new           
#> x         0x7fb19adcd378 0x7fb19ab9bcb8
#> y         0x7fb19adcd3d0 0x7fb19ab9bd10
#> z                        0x7fb19ab9bd68
#> 
#> Changed attributes:
#>           old            new           
#> names     0x7fb19adcce98 0x7fb1944e4558
#> row.names 0x7fb19ab2bd10 0x7fb19ab2bf20
#> class     0x7fb19ad5d208 0x7fb19ab51b28

dplyr で同じことを行うと、元の列はコピーされません。

df3 <- dplyr::mutate(df, z = x + y)
changes(df, df3)
#> Changed variables:
#>           old new           
#> z             0x7fb19adcd060
#> 
#> Changed attributes:
#>           old            new           
#> names     0x7fb19adcce98 0x7fb1944e8b18
#> row.names 0x7fb19ab9c0d8 0x7fb19ab9c340
#> class     0x7fb19ad5d208 0x7fb19ad69408

これにより、dplyr はベース R よりもはるかに高速になります。

Data.table は、データ テーブルをその場で変更できるため、少し高速です。ポインターを列にコピーする必要さえありません。その場で変更しないと、少し遅くなるという犠牲を払って(通常のRセマンティクスを維持するため)dplyrが少し理解しやすくなると思います(ただし、コストは行数ではなく列数に応じて増加します)。

于 2014-02-11T14:31:47.627 に答える