Home > OS >  Calculate formula from string saved in variable
Calculate formula from string saved in variable

Time:11-26

Sorry, but I'm struggling with a quite simple problem: A formula/an expression like 1.28*10^2 is saved as a character in a data frame. Now I want to convert this string into a numeric value - this should result in "128", but it does not.

library(dplyr)

mydata <- data.frame(
  formula = c("5.89*10^3", "1.28*10^2", "4.11*10^5")
)

mydata <- mydata %>% 
  dplyr::mutate(eval = eval(parse(text = formula)))

The variable "eval" should contain the values 5890, 128 and 411000 in the end.

Can anyone help where my mistake is? Thank you!

CodePudding user response:

Yet another solution, based on rlang::parse_expr:

library(dplyr)
library(rlang)

mydata <- data.frame(
  formula = c("5.89*10^3", "1.28*10^2", "4.11*10^5")
)

mydata %>% 
  rowwise %>% 
  mutate(eval = eval(parse_expr(formula)))

#> # A tibble: 3 × 2
#> # Rowwise: 
#>   formula     eval
#>   <chr>      <dbl>
#> 1 5.89*10^3   5890
#> 2 1.28*10^2    128
#> 3 4.11*10^5 411000

CodePudding user response:

By default eval(parse()) is not vectorized. Here are a couple of workarounds,

sapply(mydata$formula, function(i)eval(parse(text = i)))
#5.89*10^3 1.28*10^2 4.11*10^5 
#     5890       128    411000 

f1 <- function(x)eval(parse(text = x))
f2 <- Vectorize(f1)
mydata %>% 
  dplyr::mutate(eval = f2(formula))

  formula   eval
#1 5.89*10^3   5890
#2 1.28*10^2    128
#3 4.11*10^5 411000

CodePudding user response:

I dont think we must use rowwise. A simple lapply/purrr::map will do the job

library(purrr)
library(dplyr)
library(rlang)

mydata %>%
    mutate(result = map_dbl(formula, ~eval(parse_expr(.x))))

We can also use base R with lapply:

mydata$formula[]<-lapply(mydata$formula, \(x) eval(parse(text=x)))

  formula
1    5890
2     128
3  411000

CodePudding user response:

1) Perform one conversion at a time:

library(dplyr)

mydata %>% 
  rowwise %>%
  mutate(eval = eval(parse(text = formula))) %>%
  ungroup
## # A tibble: 3 x 2
##   formula     eval
##   <chr>      <dbl>
## 1 5.89*10^3   5890
## 2 1.28*10^2    128
3 4.11*10^5 411000

2) or use sapply:

mydata %>%
  mutate(eval = sapply(parse(text = formula), eval))

3) If all the formulas are of the form shown in the question then we can convert them to e notation and use as.numeric:

mydata %>%
  mutate(eval = as.numeric(sub('*10^', 'e', formula, fixed = TRUE)))

4) Without dplyr (2) and (3) could be done like this:

transform(mydata, eval = sapply(parse(text = formula), eval))

transform(mydata, eval = as.numeric(sub('*10^', 'e', formula, fixed = TRUE)))
  • Related