R - multiple loop counter variables

不羁的心 提交于 2020-01-25 10:11:13

问题


I need to write loops where each iteration has a unique set of variable values. It is not a nested loop "for each i do (for each j do)" type problem. Below is just an example problem, what the loop is doing is not important, it is being able to use multiple variables for each iteration for the loop.

simple loop:

df <- data.frame(num = 1:5)
lookup <- data.frame(colors = c("red", "green", "blue"), 
                     pets = c("cat", "dog", "rabbit"),
                     stringsAsFactors = FALSE)
for (color in lookup$colors) {
  df[, color] <- 1
}

what I want to do (pseudo code):

for (color, pet in lookup$colors, lookup$pets) {
  df[, color] <- pet
}

The best approach I have come up with is below, but the additional r[" "] makes the code harder to read:

for (i in 1:nrow(lookup)) {
  r <- unlist(lookup[i, ])
  df[, r["colors"]] <- r["pets"]
}

df
  num red green   blue
1   1 cat   dog rabbit
2   2 cat   dog rabbit
3   3 cat   dog rabbit
4   4 cat   dog rabbit
5   5 cat   dog rabbit

I would like to know what the best generalisable approach to this kind of problem is. In many cases, you could replace the loop with a function to be called for each set of variables, but functions aren't suitable in certain cases.


回答1:


For your specific example, you're going at it with the right mindset. To clean it up a little and reduce the chance of bugs, you could rewrite the loop as:

for (i in seq_len(nrow(lookup))) {
  color_i <- lookup[i, "colors"]
  pet_i <- lookup[i, "pets"]
  df[[color_i]] <- pet_i
}

Not that different, but seq_len avoids problems where lookup has zero rows. In that case, 1:nrow(lookup) returns c(1, 0). And whether or not my loop's guts are easier to read is probably subjective.

In case it helps, a one-line solution to your specific problem is this:

df[, lookup[["colors"]]] <- lapply(lookup[["pets"]], rep, nrow(df))

Tangentially related

I will say your example is a special case in R where you're iteratively modifying an existing object. Most of the time, people just want to iterate over multiple vectors and store the results in a new vector. For example:

results <- list()

for (i in seq_len(nrow(lookup))) {
  color_i <- lookup[i, "colors"]
  pet_i <- lookup[i, "pets"]
  results[[i]] <- do_something(color_i, pet_i)
}

A better way to do this is with mapply:

results <- mapply(FUN = do_something, lookup[["colors"]], lookup[["pets"]])


来源:https://stackoverflow.com/questions/48788983/r-multiple-loop-counter-variables

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!