有谁知道 replicate() 函数在 R 中是如何工作的,以及它相对于使用 for 循环的效率如何?
例如,...之间是否存在效率差异?
means <- replicate(100000, mean(rnorm(50)))
和...
means <- c()
for(i in 1:100000) {
means <- c(means, mean(rnorm(50)))
}
(我可能在上面打了一些字,但你明白了。)
有谁知道 replicate() 函数在 R 中是如何工作的,以及它相对于使用 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
最终是一个.Internal
用 C 语言编写的函数,并以优化的方式执行循环,而不是通过解释器。它的主要优点是高效的内存管理,特别是与您上面介绍的高效低效的向量增长方法相比。
我有一个非常不同的经历,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)
and 创建了一个函数,在比较中没有区别。基本上我没有提供任何显示replicate
.
矢量化是它们之间的关键区别。我将托盘解释这一点。R 是一种高级解释的计算机语言。它为您处理许多基本的计算机任务。当你写
x <- 2.0
你不必告诉你的电脑
R 自己计算这些东西。
但是,对于这样舒适的问题,这是有代价的:它比低级语言慢。
在 C 或 FORTRAN 中,大部分“测试是否”将在编译步骤期间完成,而不是在程序执行期间完成。它们在编写后但在运行之前被翻译成二进制计算机语言 (0/1)。这允许编译器以最佳方式组织二进制机器代码以供计算机解释。
这与 R 中的向量化有什么关系?嗯,许多 R 函数实际上是用编译语言编写的,例如 C、C++ 和 FORTRAN,并且有一个小的 R“包装器”。这是您的方法之间的区别。for
循环添加test if
机器必须对数据执行的进一步操作,使其变慢