0

I'd like generate a list of data.frames inside nested loops similar to this question. In the second loop, j should be 4, then 5 but it only runs as 5. Is the error with my function or in the way I'm using nested loops?

df=data.frame(Value=c(11,4,6,10,7,2)) 

exceedance_fun= function(x,y){ 
z=case_when(
  x > y ~ "No",
  x <= y ~ paste(y,"mg/L"),
  TRUE ~ "unsure"
)
return(z)
}  

datalist = list()

for (i in 1:2) {
for (j in 4:5) {
dat=df %>%
mutate(Vio= exceedance_fun(Value,j))
dat$i <- i
datalist[[i]] <- dat 
}
}

Incorrect Output

[[1]]
Value    Vio i
1    11     No 1
2     4 5 mg/L 1  #This should be 4 mg/L
3     5 5 mg/L 1  #This should be 4 mg/L
4    10     No 1
5     7     No 1
6     2 5 mg/L 1  #This should be 4 mg/L

[[2]]
Value    Vio i
1    11     No 2
2     4 5 mg/L 2
3     5 5 mg/L 2
4    10     No 2
5     7     No 2
6     2 5 mg/L 2
4
  • Here, you are comparing a vector of length 1 with >1 and expect an output of length 1. Did you meant to wrap with all or any in the function? Commented Sep 23, 2019 at 17:46
  • Here is a problem: datalist[[i]] <- dat the second time through the j loop you are overwriting the value inside "datalist" Commented Sep 23, 2019 at 17:47
  • j runs for both 4 and 5, but since i is the same for both, datalist[[i]] <- dat saves only the last one. Commented Sep 23, 2019 at 17:49
  • If you remove the outer for loop you will get your expected results Commented Sep 23, 2019 at 17:50

1 Answer 1

1

Here's how I would recommend restructuring in the general case where you are changing multiple parameters meaningfully:

params = expand.grid(i = 1:2, j = 4:5)
datalist = list()

for (k in 1:nrow(params)) {
  datalist[[k]] = df %>%
    mutate(Vio= exceedance_fun(Value,param$j[k]),
           i = params$i[k])
}

I'd also recommend using more descriptive variable names than i and j, but I can't tell what those are.


However, in this case, i doesn't really do anything, so a single for loop is probably fine:

j_vals = 4:5
datalist = list()

for (i in seq_along(j_vals)) {
  datalist[[i]] = df %>%
    mutate(Vio= exceedance_fun(Value, j_vals[i]),
           i = i)
}

Though it seems like it might be more useful to record j than i...

Sign up to request clarification or add additional context in comments.

2 Comments

This is close, but it produces a list with 4 data.frames. There should only be 2 in the list i.e. one with 4 mg/L and one with 5mg/L. Manually typing 4 and then 5 in the original code for j produces the correct output. @Gregor
@W148SMH See the bottom starting with However, in this case, i doesn't really do anything, so a single for loop is probably fine...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.