Is there a way to add a new column based on the previous value of a mutate() calculation?

In the below dataset, if Loc==1, I want to calculate a value, but if Loc!=1, I want to calculate a value based on the value I calculated at Loc==1, then based on the value calcuated at Loc==2 , etc. I know I can accomplish this in a loop, but I'm trying to avoid loops if I can help it. It should look something like this, note that the previous object doesn't actually exist, it's just a placeholder to better explain what I'm looking for.

data2 <- data %>%
  mutate(Residual = ifelse(Loc==1,
                           pmin(XD_VD+SE, val), # first/previous calc
                           pmin(previous + SE, val))) # second calc based on first calc

I tried this:

data2 <- data %>%
  mutate(Residual = pmin(XD_VD + SE, val),
         Residual = ifelse(Loc==1,
                           Residual,
                           pmin(lag(Residual,1)+SE, value))

However, this doesn't work as it calculates the equation based on Residual and not on the previous calculation. If anyone knows a way to do this, that would be most appreciated! Here is a reprex of my data:

data <- structure(list(Loc = 1:5, val = c(29, 49, 44, 50, 37), XD = c(66.12, 
66.12, 66.12, 66.12, 66.12), VD = c(30.1780172853143, 30.1780172853143, 
30.1780172853143, 30.1780172853143, 30.1780172853143), XD_VD = c(35.9419827146857, 
35.9419827146857, 35.9419827146857, 35.9419827146857, 35.9419827146857
), SE = c(0.77, 0.77, 0.77, 0.77, 0.77)), row.names = c(NA, -5L
), class = c("tbl_df", "tbl", "data.frame"))

When there is dependency between iterations, for loops are easier to use.

just making sure I understand, you want the actual result to be this?

loc        1   2        3           4          ...
Residual  29  29+0.77  29.77+0.77  30.54+0.77  ...

or do you want it to be this:

loc        1   2        3           4          ...
Residual  29  29+0.77  36.67+0.77  36.67+0.77  ...

In the first case, seems to me like a for loop (or a recursive function) is the way to go, vectorized approaches assume that each element can be computed independently.

In the second case, your code looks like it's doing it already.

1 Like
data2 <- data %>%
  mutate(Residual = purrr::accumulate2(SE, val,
                                \(x, y, z){
                                  min(x + y, z)
                                },
                                .init = XD_VD[Loc==1]))[-1]
1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.