我完全相信高效的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))))
正如您所看到的,内部函数会导致构建向量的长度爆炸 而使用里面的和将把所有东西都折成单值
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))))
我想要的是N的程度列表。 所以你怎么看?我怎么修理它?
答案 0 :(得分:7)
您的问题不包含可重现的代码(什么是“eps”?),但关于for循环和优化代码的一般观点:
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])
}
这实际上并不是特别慢 - 因为你正在写一个向量而你已经预先指定了长度。而且由于data.frames实际上是同等大小的向量列表,你甚至可以解决使用这个在data.frames上运行for循环的一些问题。如果您只是写入data.frame中的单个列,只需将其创建为向量,然后通过df$new_col <- output
将其写入data.frame。你将得到相同的输出,就好像你已经遍历data.frame,但它会更快地工作,因为你只需要修改它一次。