有没有人知道replicate()函数在R中是如何工作的以及它与使用for循环相比有多高效?
例如,......之间存在效率差异吗?
means <- replicate(100000, mean(rnorm(50)))
和...
means <- c()
for(i in 1:100000) {
means <- c(means, mean(rnorm(50)))
}
(我可能在上面略微输入了一些东西,但你明白了。)
答案 0 :(得分:14)
您可以对代码进行基准测试,并根据经验获得答案。请注意,我还添加了第二个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
一样快。
答案 1 :(得分:8)
replicate
是sapply
的包装器,它本身就是lapply
的包装器。 lapply
最终是一个用{C}编写的.Internal
函数,以优化的方式执行循环,而不是通过解释器。它的主要优点是高效的内存管理,特别是与上面提到的效率极低的矢量增长方法相比。
答案 2 :(得分:1)
我与replicate
的体验非常不同,这也让我感到困惑。当我使用replicate
与for
相比时,我的R崩溃并且我的笔记本电脑经常挂起,这让我感到惊讶,因为上面提到的原因,我也期望C编写的函数优于{ {1}}循环。例如,如果您执行以下功能,则会发现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
循环显然更快。如果重复100次重复,则会得到类似的结果。所以我想知道是否有人可以提供一个显示其实用特权的示例与for
相比。
PS我还为for
创建了一个函数,并且在比较中没有任何区别。基本上我没有提供任何显示runif(1e7)
优势的例子。
答案 3 :(得分:1)
矢量化是它们之间的关键区别。我将托盘解释这一点。 R是一种高级解释的计算机语言。它可以为您完成许多基本的计算机任务。当你写
x <- 2.0
您无需告诉您的计算机
R本身就是这些东西。
但是,对于这样一个舒适的问题,有一个代价:它比低级语言慢。
在C或FORTRAN中,大部分内容&#34;测试是否&#34;将在编译步骤期间完成,而不是在程序执行期间完成。它们在写入之后被翻译成二进制计算机语言(0/1),但在它们运行之前。这允许编译器以最佳方式组织二进制机器代码,供计算机解释。
这与R中的矢量化有什么关系?好吧,许多R函数实际上是用编译语言编写的,比如C,C ++和FORTRAN,并且有一个小的R“包装器”。这是你的方法之间的差异。 for
循环添加了机器必须对数据执行的更多test if
次操作,使其更慢