...关于执行时间和/或内存。
如果这不是真的,请用代码片段证明这一点。请注意,矢量化带来的加速不算在内。加速必须来自 apply
(tapply
, sapply
, ...) 本身。
最佳答案
apply
R 中的函数并未提供比其他循环函数更高的性能(例如 for
)。一个异常(exception)是 lapply
它可能会快一点,因为它在 C 代码中比在 R 中完成更多的工作(请参阅 this question for an example of this )。
但一般来说,规则是为了清晰起见,您应该使用 apply 函数,而不是为了性能。
我想补充一点,应用函数有 no side effects ,这是使用 R 进行函数式编程时的一个重要区别。这可以通过使用 assign
来覆盖。或<<-
,但这可能非常危险。副作用还会使程序更难理解,因为变量的状态取决于历史记录。
编辑:
只是为了强调这一点,用一个递归计算斐波那契数列的简单例子;这可以运行多次以获得准确的测量结果,但关键是这些方法都没有显着不同的性能:
fibo <- function(n) {
if ( n < 2 ) n
else fibo(n-1) + fibo(n-2)
}
system.time(for(i in 0:26) fibo(i))
# user system elapsed
# 7.48 0.00 7.52
system.time(sapply(0:26, fibo))
# user system elapsed
# 7.50 0.00 7.54
system.time(lapply(0:26, fibo))
# user system elapsed
# 7.48 0.04 7.54
library(plyr)
system.time(ldply(0:26, fibo))
# user system elapsed
# 7.52 0.00 7.58
编辑 2:
关于 R 并行包的使用(例如 rpvm、rmpi、snow),这些通常会提供 apply
系列函数(即使是 foreach
包本质上是等效的,尽管有名称)。这是 sapply
的一个简单示例函数位于 snow
:
library(snow)
cl <- makeSOCKcluster(c("localhost","localhost"))
parSapply(cl, 1:20, get("+"), 3)
本例使用socket集群,不需要安装额外的软件;否则您将需要 PVM 或 MPI 之类的东西(请参阅 Tierney's clustering page )。 snow
具有以下应用功能:
parLapply(cl, x, fun, ...)
parSapply(cl, X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE)
parApply(cl, X, MARGIN, FUN, ...)
parRapply(cl, x, fun, ...)
parCapply(cl, x, fun, ...)
这是有道理的 apply
函数应该用于并行执行,因为它们没有 side effects 。当您更改 for
内的变量值时循环,它是全局设置的。另一方面,所有apply
函数可以安全地并行使用,因为更改是函数调用的本地更改(除非您尝试使用 assign
或 <<-
,在这种情况下可能会引入副作用)。不用说,小心局部变量和全局变量至关重要,尤其是在处理并行执行时。
编辑:
这是一个简单的示例,用于演示 for
之间的差异和*apply
就副作用而言:
df <- 1:10
# *apply example
lapply(2:3, function(i) df <- df * i)
df
# [1] 1 2 3 4 5 6 7 8 9 10
# for loop example
for(i in 2:3) df <- df * i
df
# [1] 6 12 18 24 30 36 42 48 54 60
注意df
是如何父环境中的内容被 for
更改但不是*apply
.
关于r - R 的 apply 系列不仅仅是语法糖吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2275896/