0

I wish to generate new columns based on receiving variables in tidy evaluation. For example,

library(dplyr)

some_custom_measure <- function(.data, cola, colb) {
    .data %>% mutate("{{ cola }}_x_{{ colb }}" := {{ cola }} * {{ colb }})
}
iris %>% 
    some_custom_measure(Sepal.Length, Sepal.Width) %>% 
    head()

The new column will be named Sepal.Length_x_Sepal.Width.

How do I manipulate the variables as string when forming new name in the custom function? I wish to accomplish something like sepal_length_x_sepal_width

ThomasJc
  • 131
  • 9

1 Answers1

2

You can use deparse(substitute(...)) to capture each variable name as a string and store it to a variable.

You can then process that variable however you like to manipulate the string. When you come to use it, put the variable inside single curly brackets in your column name specification.

library(dplyr)

some_custom_measure <- function(.data, cola, colb) {

    cola_name <- tolower(gsub("\\.", "_", deparse(substitute(cola))))
    colb_name <- tolower(gsub("\\.", "_", deparse(substitute(colb))))

    .data %>% mutate("{cola_name}_x_{colb_name}" := {{ cola }} * {{ colb }})
}

iris %>% 
    some_custom_measure(Sepal.Length, Sepal.Width) %>% 
    head()
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa
#>   sepal_length_x_sepal_width
#> 1                      17.85
#> 2                      14.70
#> 3                      15.04
#> 4                      14.26
#> 5                      18.00
#> 6                      21.06
Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Thanks! Also, I figure out there is `as_name(enquo(...))` in `rlang` – ThomasJc Dec 17 '20 at 11:28
  • 4
    I recommend using `rlang::as_label()` which, unlike `deparse()`, is guaranteed to return a length 1 string. The `rlang::as_name()` variant additionally checks that the input is a single name, whereas `as_label()` works with any expression. – Lionel Henry Dec 17 '20 at 11:37