7

レプリケート() 関数が R でどのように機能するか、また for ループの使用に比べてどれだけ効率的かを知っている人はいますか?

たとえば、効率の違いはありますか...

means <- replicate(100000, mean(rnorm(50)))

と...

means <- c()
for(i in 1:100000) { 
   means <- c(means, mean(rnorm(50)))
}

(上で少し間違って入力したかもしれませんが、おわかりいただけると思います。)

4

4 に答える 4

15

コードをベンチマークして、経験的に答えを得ることができます。ベクトルを事前に割り当てることにより、増大するベクトルの問題を回避する 2 番目の for ループ フレーバーも追加したことに注意してください。

repl_function = function(no_rep) means <- replicate(no_rep, mean(rnorm(50)))
for_loop = function(no_rep) {
   means <- c()
   for(i in 1:no_rep) { 
      means <- c(means, mean(rnorm(50)))
   }
   means
}
for_loop_prealloc = function(no_rep) {
   means <- vector(mode = "numeric", length = no_rep)
   for(i in 1:no_rep) { 
      means[i] <- mean(rnorm(50))
   }
   means
}

no_loops = 50e3
benchmark(repl_function(no_loops), 
          for_loop(no_loops), 
          for_loop_prealloc(no_loops), 
          replications = 3)

                         test replications elapsed relative user.self sys.self
2          for_loop(no_loops)            3  18.886    6.274    17.803    0.894                          
3 for_loop_prealloc(no_loops)            3   3.209    1.066     3.189    0.000                          
1     repl_function(no_loops)            3   3.010    1.000     2.997    0.000                          
  user.child sys.child
2          0         0                                                                                  
3          0         0                                                                                  
1          0         0 

列を見ると、relative事前割り当てされていない for ループは 6.2 倍遅くなります。ただし、事前に割り当てられた for ループは と同じくらい高速replicateです。

于 2012-11-16T08:34:27.600 に答える
8

replicateのラッパーでsapplyあり、それ自体が のラッパーですlapplylapply最終的に.Internalは、C で記述された関数であり、インタープリターを使用するのではなく、最適化された方法でループを実行します。その主な利点は、特に上記で提示した非常に非効率的なベクトル成長方法と比較して、効率的なメモリ管理です。

于 2012-11-16T07:46:59.797 に答える
1

私は非常に異なる経験をしており、replicateそれも私を混乱させています。replicateと比較して使用すると、R がクラッシュしてラップトップがハングすることがよくありますがfor、これは驚くべきことです。上記の理由から、C で作成された関数がforループよりも優れていると予想していました。たとえば、以下の関数を実行すると、forループがより高速であることがわかります。replicate

system.time(for (i in 1:10) runif(1e7))
#    user  system elapsed 
#    3.340   0.218   3.558 

system.time(replicate(10, runif(1e7)))
#    user  system elapsed 
#    4.622   0.484   5.109

したがって、10複製を使用すると、forループは明らかに高速になります。これを 100 回繰り返すと、同様の結果が得られます。だから、誰かが と比較してその実用的な特権を示す例を持ってくることができるのだろうかfor.

PS私はまた、runif(1e7)との関数を作成しましたが、比較に違いはありませんでした。基本的に、 の利点を示す例はありませんでしたreplicate

于 2016-04-25T17:33:51.260 に答える