tapplyの再実装で高速化

applyとかtapplyとか遅い。Rcppで楽したい。けど苦労はしたくない。
そんなときKmiscパッケージのrcpp_tapply_generator関数が役に立ちます。
使い方は簡単。tapply関数のFUNをreturnとともに放り込むだけ。

install.packages("Kmisc")
library(Kmisc)
cppTapply <- rcpp_tapply_generator("return mean(x);")

速さを測ってみます。

install.packages("microbenchmark")
library(microbenchmark)

microbenchmark(
  tapply(iris$Sepal.Length, iris$Species, mean),
  cppTapply(iris$Sepal.Length, iris$Species),
  iris %>% group_by(Species) %>% summarise(mean(Sepal.Length))
)

結果はこちら。tapply、dplyrと比較してみます。

Unit: microseconds
                                                         expr     min       lq       mean   median        uq      max neval
                   cppTapply(iris$Sepal.Length, iris$Species)  58.164  69.6605   88.51962  81.5005   97.1935  246.737   100
                tapply(iris$Sepal.Length, iris$Species, mean) 197.400 208.8065  238.16384 228.1135  245.9890  456.475   100
 iris %>% group_by(Species) %>% summarise(mean(Sepal.Length)) 850.581 958.0700 1013.35200 986.1895 1025.5135 1731.105   100

速い!!!
ちなみにKmiscパッケージにはtapply_という関数も用意されています。
こちらは高速化を図ってtapplyを再実装したもの。
使い方はtapplyと同じ。

Unit: microseconds
                                                         expr     min        lq       mean    median        uq      max neval
               tapply_(iris$Sepal.Length, iris$Species, mean)  69.436   79.5705   90.45106   84.4310   97.9000  146.773   100
                   cppTapply(iris$Sepal.Length, iris$Species)  58.522   68.2020   79.83578   76.7925   86.0465  140.197   100
                tapply(iris$Sepal.Length, iris$Species, mean) 198.723  217.0880  235.40915  233.7335  247.2670  378.604   100
 iris %>% group_by(Species) %>% summarise(mean(Sepal.Length)) 886.211 1006.8870 1039.99144 1036.3295 1064.0005 1360.138   100

そんなに変わらない気がするのでtapply_でいいかもしれません。
enjoy!!!