Parse and Evaluate Column of String Expressions in R?

丶灬走出姿态 提交于 2021-01-27 11:39:58

问题


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.


回答1:


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, ......).




回答2:


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



回答3:


Note that values of additional variables (such as iter=1 in your case) can be passed directly to eval():

df %>% 
  mutate( evaluated = map_dbl(to_evaluate, ~eval(parse(text=.x), list(iter=1))) )

One advantage is that it automatically restricts the scope of the variable, keeping its value right next to where it is used.



来源:https://stackoverflow.com/questions/57349214/parse-and-evaluate-column-of-string-expressions-in-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!