9

Almost as soon as you finish your introduction to R, where you probably learned the syntax for a for loop, you are told to avoid for loops in R!

R is a vectorized language, so you are told to NEVER do things like

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

and instead do

z = x + y

You are also told to use the family of *ply functions for iterative looping purposes.

My question is, other than potential code readability scenarios, is there ever a good time to use for loops in R?

NewNameStat
  • 2,474
  • 1
  • 19
  • 26
  • 2
    Suppose you want to assign the value in each run and use that value for subsequent runs, a `for` loop can be used. Though `Reduce` have similar potential, I think `for` loop is better in that. – akrun Apr 06 '16 at 12:12
  • 1
    See R Inferno by Patrick Burns. Loops are fine as long as you preallocate objects. If you want super speeds, you're better off with some specialized techniques like using `data.table` or tapping the power of `Rcpp`. – Roman Luštrik Apr 06 '16 at 12:50
  • 1
    This sort of question has been asked before. @germcd has found the link for you. http://chat.stackoverflow.com/transcript/message/29792007#29792007 – Roman Luštrik Apr 06 '16 at 13:11
  • [this](http://stackoverflow.com/questions/2275896/is-rs-apply-family-more-than-syntactic-sugar) question is also related – germcd Apr 06 '16 at 13:21
  • Whenever you _can't_ vectorize?! – Marc in the box Apr 06 '16 at 14:04
  • When I can't vectorize, I *ply. – NewNameStat Apr 06 '16 at 14:09
  • *ply = split, apply(usually vectorized operation), combine – Marc in the box Apr 06 '16 at 15:09

2 Answers2

9

Advanced R mentions three cases for loops: modifying in place, recursive functions and while loops. Since you are asking for for loops, here is what is written on the first two cases:

Modifying in place

If you need to modify part of an existing data frame, it’s often better to use a for loop. For example, the following code performs a variable-by-variable transformation by matching the names of a list of functions to the names of variables in a data frame.

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]])
}

We wouldn’t normally use lapply() to replace this loop directly, but it is possible.

Recursive relationships

It’s hard to convert a for loop into a functional when the relationship between elements is not independent, or is defined recursively. For example, exponential smoothing works by taking a weighted average of the current and previous data points. The exps() function below implements exponential smoothing with a for loop.

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

We can’t eliminate the for loop because none of the functionals we’ve seen allow the output at position i to depend on both the input and output at position i - 1.

sebastianmm
  • 1,148
  • 1
  • 8
  • 26
  • 1
    Advanced R refers just to situation when a for loop is better for readability purposes, which is not what he was asking – adaien Apr 06 '16 at 23:51
5

Creating a multipage pdf of graphs. Or really anything that takes a long time each iteration, as the generation of a plot does. If the loop isn't the bottleneck, it's almost always more readable that way to me, so I do it.

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()
cory
  • 6,529
  • 3
  • 21
  • 41
  • This is actually the exact motivation for my question! I did exactly this and said to myself "huh when's the last time I wrote a for loop in R?" – NewNameStat Apr 06 '16 at 13:01