有誰知道R中的replicate()函數是如何工作的以及它相對於使用for循環的效率如何?複製()與for循環?
例如,是否有任何之間的效率差異的...
means <- replicate(100000, mean(rnorm(50)))
而且......
means <- c()
for(i in 1:100000) {
means <- c(means, mean(rnorm(50)))
}
(我可能鍵入一些稍微偏離上面,但你的想法。 )
有誰知道R中的replicate()函數是如何工作的以及它相對於使用for循環的效率如何?複製()與for循環?
例如,是否有任何之間的效率差異的...
means <- replicate(100000, mean(rnorm(50)))
而且......
means <- c()
for(i in 1:100000) {
means <- c(means, mean(rnorm(50)))
}
(我可能鍵入一些稍微偏離上面,但你的想法。 )
您可以對代碼進行基準測試並根據經驗得出答案。請注意,我還添加了第二個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
一樣快。
replicate
是sapply
的包裝,它本身是lapply
的包裝。 lapply
最終是一個用C語言編寫的.Internal
函數,並以優化的方式執行循環,而不是通過解釋器。它的主要優點是高效的內存管理,特別是與上面介紹的非常低效的向量增長方法相比。
我與replicate
有一個非常不同的經驗,這也使我困惑。當我使用replicate
與for
相比時,經常發生我的R崩潰和我的筆記本電腦掛起,這讓我感到驚訝,至於上述原因,我還希望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
優勢的例子。
矢量化是它們之間的關鍵區別。我會托盤解釋這一點。 R是一種高級解釋的計算機語言。它爲您處理許多基本的計算機任務。當你寫
x <- 2.0
你不必告訴您的計算機
R自己計算這些東西。
但是,爲了這樣舒適的問題,有一個價格:它比低級語言慢。
在C或FORTRAN中,大部分此「測試if」將在編譯步驟中完成,而不是在程序執行過程中完成。它們在寫入之後被翻譯成二進制計算機語言(0/1),但在它們運行之前。這允許編譯器以計算機解釋的最佳方式組織二進制機器代碼。
這與R中的矢量化有什麼關係?那麼,許多R函數實際上是用一種編譯語言編寫的,比如C,C++和FORTRAN,並且有一個小的R「包裝器」。這是你方法的區別。 for
循環進一步添加test if
機器必須對數據執行的操作,使其變得更慢
預分配for循環與「replicate」一樣快。我認爲這是因爲代碼的主要部分是在R中花費的。例如,在「mean」周圍重新實現整個循環。 C++可能會加快速度。看到我的答案中的基準。 –