確かに apply は遅い。その代わりに colMeans, rowSums を使って定義通りに書くと,ヘタに行列演算するより速い。
colMeans, rowSums を使って書いたものと,結果の格納領域を事前に確保して行列演算をするのは,ほとんど同じくらいの速度である。
それでもまあ,実行時間は1秒ミマンなのだから,こんな細かいことを言っても,毒にも薬にもならぬ。
> # apply
> Rprof()
> varA <- apply(d, 2, var)
> Rprof(NULL)
> print(a <- summaryRprof()$sampling.time)
[1] 3.56
> # colMeans, rowSums
> Rprof()
> means <- colMeans(d)
> varA2 <- rowSums((t(d)-means)^2)/(n-1)
> Rprof(NULL)
> print(a2 <- summaryRprof()$sampling.time)
[1] 0.1
> all.equal(varA, varA2) # 結果が一致していることを確認
[1] TRUE
行列演算を使うと速いけど,cbind( ) を使って結果をつなげてゆくなんてことをすると,遅くなってしまう。
> # matrix operation (2)
> Rprof()
> varC <- NULL
> for(i in 1:1000) {
+ varC <- cbind( # cbind でつなぐのは悪手
+ varC,
+ (rep(1, n) %*% d[,((i-1)*100+1):((i)*100)]^2 -
+ (rep(1, n) %*% d[,((i-1)*100+1):((i)*100)])^2 / n)
+ / (n - 1)
+ )}
> varC <- as.numeric(varC)
> Rprof(NULL)
> print(c <- summaryRprof()$sampling.time)
[1] 0.96
>
> # matrix operation (2-2)
> Rprof()
> varC2 <- matrix(0, 100, 1000) # 前もって必要なだけ領域を確保しておく
> for(i in 1:1000) {
+ varC2[,i] <- (rep(1, n) %*% d[,((i-1)*100+1):((i)*100)]^2 -
+ (rep(1, n) %*% d[,((i-1)*100+1):((i)*100)])^2 / n)/ (n - 1)
+ }
> varC2 <- as.vector(varC2)
> Rprof(NULL)
> print(c2 <- summaryRprof()$sampling.time)
[1] 0.08
> all.equal(varC, varC2) # 結果が一致していることを確認
[1] TRUE