Parsing “的优点是什么?”;套用;功能?什么时候使用它们比“使用”更好;至于;循环,何时不是?

Parsing “的优点是什么?”;套用;功能?什么时候使用它们比“使用”更好;至于;循环,何时不是?,parsing,r,for-loop,compilation,lapply,Parsing,R,For Loop,Compilation,Lapply,可能重复: 正如标题所说。也许是个愚蠢的问题,但我的理解是,当使用“apply”函数时,迭代是在编译代码中执行的,而不是在R解析器中执行的。例如,这似乎意味着,如果存在大量迭代且每个操作相对简单,则lappy只比“for”循环快。例如,如果对lappy中封装的函数的单个调用需要10秒,并且只有12次迭代,那么我可以想象使用“For”和“lappy”实际上没有任何区别 现在我想起来了,如果无论如何都必须解析“lappy”中的函数,为什么使用“lappy”而不是“for”会有任何性能上的好处,除非

可能重复:

正如标题所说。也许是个愚蠢的问题,但我的理解是,当使用“apply”函数时,迭代是在编译代码中执行的,而不是在R解析器中执行的。例如,这似乎意味着,如果存在大量迭代且每个操作相对简单,则lappy只比“for”循环快。例如,如果对lappy中封装的函数的单个调用需要10秒,并且只有12次迭代,那么我可以想象使用“For”和“lappy”实际上没有任何区别

现在我想起来了,如果无论如何都必须解析“lappy”中的函数,为什么使用“lappy”而不是“for”会有任何性能上的好处,除非您正在做一些有编译函数的事情(比如求和或乘法等)

提前谢谢


Josh

有几个原因可以解释为什么人们更喜欢
apply
系列函数而不是
for
循环,反之亦然

首先,
for()
apply()
sapply()
如果执行正确,通常会与对方一样快
lappy()
在R内部编译代码中的操作比其他函数要多,因此可以比这些函数更快。当数据上的“循环”行为是计算时间的重要部分时,速度优势似乎最大;在许多日常使用中,您不太可能从固有的更快的
lappy()
中获得太多好处。最后,这些都将调用R函数,因此需要对它们进行解释,然后运行

for()
循环通常更容易实现,特别是如果您来自循环盛行的编程背景。在循环中工作可能比将迭代计算强制到一个
apply
系列函数中更自然。但是,要正确使用
for()
循环,您需要做一些额外的工作来设置存储并管理将循环的输出重新插回一起。
apply
功能自动为您执行此操作。例如:

IN <- runif(10)
OUT <- logical(length = length(IN))
for(i in IN) {
    OUT[i] <- IN > 0.5
}
您应该了解为什么
lappy()
for()
与其他
apply
系列函数之间的速度会有差异。
.Internal()
是R调用自己使用的编译C代码的方法之一。除了对
FUN
进行操作和健全性检查外,整个计算都是用C语言完成的,调用R函数
FUN
。将其与Burns的
apply()

的源代码(pdf)进行比较,第25页:

当每个 迭代是一项非常重要的任务。但是 简单的循环可以更加清晰和简单 使用
apply
功能。至少有一个 这条规则的例外。。。如果结果会 是一个列表和一些组件 可以是
NULL
,则为for循环 故障(大故障)和
lappy
预期的答案


看到这个帖子了吗:这一条:2008年5月,R帮助台上也有一篇关于这个的文章:这一条:很好!你还设法在相关问题中添加了新的信息。谢谢,我学到了一些新东西。太好了,谢谢。我想澄清一件关于潜在性能增益的事情。在对lappy()的调用中执行的代码在每次迭代中仍然会花费同样长的时间,对吗?因此,我是否可以正确地指出,在每次迭代本身花费几秒钟或更长时间的情况下,相对于apply()或for()的性能增益可以忽略不计?我完全不同意。如果迭代是一项非常重要的任务,那么最好将该代码块移动到适当的函数中,然后使用*apply()调用它。
> lapply
function (X, FUN, ...) 
{
    FUN <- match.fun(FUN)
    if (!is.vector(X) || is.object(X)) 
        X <- as.list(X)
    .Internal(lapply(X, FUN))
}
<environment: namespace:base>