Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dplyr / tidyevaluation: How to pass an expression in mutate as a string?

Tags:

r

dplyr

tidyeval

I want to write a function that has two inputs: The name of a new variable and a mathematical expression. Both arguments come as strings.

This function should take a data.frame and add the specified new variable which should be the result of the given mathematical expression.

This is a minimal working example of what I tried:

df <- tibble(A = 1:10, B = 1:10)
new_var <- "C"
expression <- "A + B"


example_fun <- function(new_var, expression) {
  new_var_sym <- sym(new_var)
  expression_sym <-  sym(expression)

  mutate(df, !! new_var_sym := !! expression_sym)
}

example_fun(new_var, expression)

This yields the following error:

Error in mutate_impl(.data, dots) : Binding not found: A + B.

When I wrap the mutate line within the function with expr(), I get

mutate(df, `:=`(C, `A + B`))

It seems as if the ticks around A + B should not be there, but I could not figure out how to get rid of them. At least, enquo() and quo_name() did not help.

like image 321
der_grund Avatar asked May 25 '18 13:05

der_grund


Video Answer


1 Answers

We can have a quosure/quote as expression and then do the evaluation (!!). Also, the lhs of := can take string, so we don't need to convert the 'new_var' to symbol

library(tidyverse)
library(rlang)

expression <- quo(A + B)
example_fun <- function(new_var, expression) {


  df %>% 
      mutate(!! new_var := !! expression)
}

example_fun(new_var, expression)
# A tibble: 10 x 3
#       A     B     C
#   <int> <int> <int>
# 1     1     1     2
# 2     2     2     4
# 3     3     3     6
# 4     4     4     8
# 5     5     5    10
# 6     6     6    12
# 7     7     7    14
# 8     8     8    16
# 9     9     9    18
#10    10    10    20

If we really wanted to pass as character strings, then use parse_expr

expression <- "A + B"
example_fun <- function(new_var, expression) {


  df %>%
     mutate(!! new_var := !! parse_expr(expression))
}

example_fun(new_var, expression)
# A tibble: 10 x 3
#       A     B     C
#   <int> <int> <int>
# 1     1     1     2
# 2     2     2     4
# 3     3     3     6
# 4     4     4     8
# 5     5     5    10
# 6     6     6    12
# 7     7     7    14
# 8     8     8    16
# 9     9     9    18
#10    10    10    20
like image 107
akrun Avatar answered Oct 16 '22 15:10

akrun