我完全相信一个有效的R程序应该尽可能避免使用循环,而应该使用apply函数的大系列.但如果没有痛苦,这是不可能的.例如,我面临一个问题,其解决方案涉及应用函数中的总和,因此结果列表减少到单个值,这不是我想要的.具体来说,我会尽量简化我的问题N =100
sapply(list(1:N), function(n) (
choose(n,(floor(n/2)+1):n) *
eps^((floor(n/2)+1):n) *
(1- eps)^(n-((floor(n/2)+1):n))))
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,内部函数会导致构建向量的长度爆炸,而使用内部求和会将所有内容折叠为单值
sapply(list(1:N), function(n) (
choose(n,(floor(n/2)+1):n) *
eps^((floor(n/2)+1):n) *
(1- eps)^(n-((floor(n/2)+1):n))))
Run Code Online (Sandbox Code Playgroud)
我想要的是一个N的程度列表.那你觉得怎么样?我该怎么修呢?
您的问题不包含可重现的代码(什么是"eps"?),但关于for循环和优化代码的一般观点:
对于循环不是非常慢.由于内存分配给对象的方式不正确,因此循环速度极慢.对于原始对象(如向量),修改字段中的值的成本很小 - 但扩展向量的长度/成本相当昂贵,因为您实际上正在创建一个全新的对象,为该对象寻找空间,复制名称,删除旧对象等.对于非原始对象(比如数据帧),它甚至更昂贵,因为每次修改,即使它不改变data.frame的长度,也会触发这个处理.
但是:有一些方法可以优化for循环并使它们快速运行.最简单的指导方针是:
所以在这种情况下 - 如果你只为N中的每个东西生成一个单独的值,你可以用向量很好地完成它的工作:
#Create output object. We're specifying the length in advance so that writing to
#it is cheap
output <- numeric(length = length(N))
#Start the for loop
for(i in seq_along(output)){
output[i] <- your_computations_go_here(N[i])
}
Run Code Online (Sandbox Code Playgroud)
这实际上并不是特别慢 - 因为你正在写一个向量而你已经预先指定了长度.而且由于data.frames实际上是同等大小的向量列表,你甚至可以解决使用这个在data.frames上运行for循环的一些问题.如果您只是写入data.frame中的单个列,只需将其创建为向量,然后将其写入data.frame via df$new_col <- output.你将得到相同的输出,就像你已经循环通过data.frame,但它会更快地工作,因为你只需要修改它一次.