何时在R

时间:2016-04-06 12:00:22

标签: r performance loops vectorization

几乎在你完成R的介绍之后,你可能已经学习了for循环的语法,你被告知要避免R中的for循环!

R是一种矢量化语言,所以你被告知不要做像

这样的事情
x = 1:10
y = 2:11
z = rep(NA, 10)
for i in 1:10{    
    z[i] = x[i] + y[i]    
}

而是做

z = x + y

您还被告知使用* ply函数族来进行迭代循环。

我的问题是,除了潜在的代码可读性方案之外,是否还有很好的时间用于R中的循环?

2 个答案:

答案 0 :(得分:4)

Advanced R提到了三种情况:循环修改,递归函数和while循环。由于您要求for循环,以下是前两种情况的内容:

就地修改

如果您需要修改现有数据框的一部分,通常最好使用for循环。例如,以下代码通过将函数列表的名称与数据框中的变量名称进行匹配来执行逐个变量的转换。

trans <- list(
  disp = function(x) x * 0.0163871,
  am = function(x) factor(x, levels = c("auto", "manual"))
)
for(var in names(trans)) {
  mtcars[[var]] <- trans[[var]](mtcars[[var]])
}

我们通常不会使用lapply()直接替换此循环,但这是可能的。

递归关系

当元素之间的关系不是独立的或递归定义时,很难将for循环转换为函数。例如,指数平滑通过采用当前和先前数据点的加权平均来工作。下面的exps()函数使用for循环实现指数平滑。

exps <- function(x, alpha) {
  s <- numeric(length(x) + 1)
  for (i in seq_along(s)) {
    if (i == 1) {
      s[i] <- x[i]
    } else {
      s[i] <- alpha * x[i - 1] + (1 - alpha) * s[i - 1]
    }
  }
  s
}
x <- runif(6)
exps(x, 0.5)
#> [1] 0.6622163 0.6622163 0.4758159 0.2703593 0.1896377 0.5506731 0.7300305

我们无法消除for循环,因为我们看到的所有函数都不允许位置i的输出依赖于位置i-1的输入和输出。

答案 1 :(得分:3)

创建图表的多页pdf。或者实际上每次迭代需要很长时间的任何事情,就像情节的产生一样。如果循环不是瓶颈,它对我来说几乎总是更具可读性,所以我这样做。

pdf("file.pdf", onefile=TRUE)
for(var in unique(df$some_var)){
  p <- ggplot(df[df$some_var==var, ], aes(x=x, y=y)) + geom_line()
  print(p)
}
dev.off()