The calculation of new variable using the equation and parameters provided in separate columns in R

I have a data frame with five columns, which are needed to calculate a new variable (y):

  1. variable x (numeric)
  2. equation 1 (character)
  3. parameter a for equation 1
  4. parameter b for equation 1
  5. parameter c for equation 1
data <-  data.frame(
      x = c(3,4,5),     
      equation = c("5*x + a * 2 - pi * b", "10*x + a - log(b)", "-x + a + c"),
      a = c(1,4,8), 
      b = c(0.1,4,-8),
      c =c(1.5,0.4,18),
      y = c(NA, NA, NA),
      y_expected = c(16.69, 42.61, 21.00))

Now, for each row separately, I would like to use the equation 1 and a, b and c parameters to calculate y (see the expected y values calculated manually). I have used the following code to do it, but the result is not correct. What happens here is that the y variable is calculate using the equation from column 3.

library(dplyr)
mutate(data, y = eval(parse(text=equation)))

  x             equation a    b    c    y y_expected
1 3 5*x + a * 2 - pi * b 1  0.1  1.5 -0.5      16.69
2 4    10*x + a - log(b) 4  4.0  0.4  0.4      42.61
3 5           -x + a + c 8 -8.0 18.0 21.0      21.00
Warning message:
Problem with `mutate()` column `y`.
i `y = eval(parse(text = equation))`.
i NaNs produced 

How can I fix this? I know I can achieve the solution using the for loop, but I am striking for more elegant solution.

list1 <- list()
for (i in 1:nrow(data)){
  
  temp_df <- data[i, ]
  temp_df <- mutate(temp_df, y = eval(parse(text=equation)))
  list1[[i]] <- temp_df
}
do.call(rbind, list1)

  x             equation a    b    c        y y_expected
1 3 5*x + a * 2 - pi * b 1  0.1  1.5 16.68584      16.69
2 4    10*x + a - log(b) 4  4.0  0.4 42.61371      42.61
3 5           -x + a + c 8 -8.0 18.0 21.00000      21.00

Solution 1:

dplyr::rowwise() should do the trick...


library(dplyr)
data %>% 
  rowwise() %>% 
  mutate(y = eval(parse(text=equation)))

#> # A tibble: 3 x 7
#> # Rowwise: 
#>       x equation                 a     b     c     y y_expected
#>   <dbl> <chr>                <dbl> <dbl> <dbl> <dbl>      <dbl>
#> 1     3 5*x + a * 2 - pi * b     1   0.1   1.5  16.7       16.7
#> 2     4 10*x + a - log(b)        4   4     0.4  42.6       42.6
#> 3     5 -x + a + c               8  -8    18    21         21

Created on 2022-01-24 by the reprex package (v2.0.1)