Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse and Evaluate Column of String Expressions in R?

How can I parse and evaluate a column of string expressions in R as part of a pipeline?

In the example below, I produce my desired column, evaluated. But I know this isn't the right approach. I tried taking a tidyverse approach. But I'm just very confused.

library(tidyverse)
df <- tibble(name = LETTERS[1:3], 
             to_evaluate = c("1-1+1", "iter+iter", "4*iter-1"), 
             evaluated = NA)
iter = 1
for (i in 1:nrow(df)) {
  df[i,"evaluated"] <- eval(parse(text=df$to_evaluate[[i]]))
}
print(df)
# # A tibble: 3 x 3
# name  to_evaluate evaluated
# <chr> <chr>           <dbl>
# 1 A     1-1+1               1
# 2 B     iter+iter           2
# 3 C     4*iter-1            3

As part of a pipeline, I tried:

df %>% mutate(evaluated = eval(parse(text=to_evaluate)))
df %>% mutate(evaluated = !!parse_exprs(to_evaluate))
df %>% mutate(evaluated = parse_exprs(to_evaluate))
df %>% mutate(evaluated = eval(parse_expr(to_evaluate)))
df %>% mutate(evaluated = parse_exprs(to_evaluate))
df %>% mutate(evaluated = eval(parse_exprs(to_evaluate)))
df %>% mutate(evaluated = eval_tidy(parse_exprs(to_evaluate)))

None of these work.

like image 886
lowndrul Avatar asked Jan 31 '26 06:01

lowndrul


2 Answers

You can try:

df %>%
 rowwise() %>%
 mutate(iter = 1,
        evaluated = eval(parse(text = to_evaluate))) %>%
 select(-iter)

  name  to_evaluate evaluated
  <chr> <chr>           <dbl>
1 A     1-1+1               1
2 B     iter+iter           2
3 C     4*iter-1            3

Following this logic, also other possibilities could work. Using rlang::parse_expr():

df %>%
 rowwise() %>%
 mutate(iter = 1,
        evaluated = eval(rlang::parse_expr(to_evaluate))) %>%
 select(-iter)

On the other hand, I think it is important to quote @Martin Mächler:

The (possibly) only connection is via parse(text = ....) and all good R programmers should know that this is rarely an efficient or safe means to construct expressions (or calls). Rather learn more about substitute(), quote(), and possibly the power of using do.call(substitute, ......).

like image 164
tmfmnk Avatar answered Feb 01 '26 18:02

tmfmnk


Here's a slightly different way that does everything within mutate.

df %>% mutate(
    evaluated = pmap_dbl(., function(name, to_evaluate, evaluated) 
                         eval(parse(text=to_evaluate)))
)

# A tibble: 3 x 3
  name  to_evaluate evaluated
  <chr> <chr>           <dbl>
1 A     1-1+1               1
2 B     iter+iter           2
3 C     4*iter-1            3
like image 41
rpolicastro Avatar answered Feb 01 '26 18:02

rpolicastro



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!