Tom H
Tom H

Reputation: 3

How do I use a string as a formula using tidyverse's mutate?

I am trying to replace the deprecated mutate_ from some legacy code. However, I haven't been able to figure out how to properly use indirection from a string. The

vignette("programming", package = "dplyr")

describes two main cases, but from my (admittedly limited) understanding, neither of these cases are quite what I need.

library(tidyverse)

#set up data frame and formula

df <- tribble(~Letter, "A", "B", "C")

Formula <- "ifelse(Letter == 'A', 'A', 'Not A')"

#using mutate_ produces the result I want
Original_Method <- df %>%
  mutate_(Original = Formula)

#correctly identifies A and not A.
Original_Method 

#From the programming vignette, I would expect this to work, but there is an error because the column doesn't exist.
Expected_Method <- df %>%
  mutate(Expected= .data[[Formula]])

#nor does it work with .data in the formula
Updated_Formula <- "ifelse(.data[[Letter]] == 'A', 'A', 'Not A')"

Expected_Method_Two <- df %>%
  mutate(Expected_Two = Updated_Formula)


#A single name formula does work

Single_Column_Name <- "Letter"

Single_Column_Method <- df %>%
  mutate(Repeat_Letter = .data[[Single_Column_Name]])

What needs to get done to properly replicate mutate_ using just mutate?

Upvotes: 0

Views: 459

Answers (1)

stefan
stefan

Reputation: 125373

One option would be to use rlang::parse_expr and rlang::eval_tidy:

library(tidyverse)

df <- tribble(~Letter, "A", "B", "C")

Formula <- "ifelse(Letter == 'A', 'A', 'Not A')"

df %>%
  mutate_(Original = Formula)
#> Warning: `mutate_()` was deprecated in dplyr 0.7.0.
#> Please use `mutate()` instead.
#> See vignette('programming') for more help
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
#> # A tibble: 3 × 2
#>   Letter Original
#>   <chr>  <chr>   
#> 1 A      A       
#> 2 B      Not A   
#> 3 C      Not A

df %>%
  mutate(Expected = rlang::eval_tidy(rlang::parse_expr(Formula), data = .))
#> # A tibble: 3 × 2
#>   Letter Expected
#>   <chr>  <chr>   
#> 1 A      A       
#> 2 B      Not A   
#> 3 C      Not A

Upvotes: 1

Related Questions