Search code examples
rfunctionvariablesdplyrdynamic

using a composite to call a variable dynmically in custom build function with dplyr (!!paste0, {{}}, as.name(), eval(parse(text=)


This is an extension of the following questions: (1), (2) and also asked in the comments to (2) by Mario Reutter.

library(dplyr, tidyverse)
string <- c("car", "train", 'bike', 'plain')
speed1 <- runif(4, min = 0, max = 10000)
speed2 <- runif(4, min = 0, max = 10000)
n1  <- sample(1:100, 4)
n1_plus  <- sample(1:100, 4)
n1_minus <- sample(1:100, 4)
n2  <- sample(1:100, 4)
df <- data.frame(string, speed1, speed2, n1, n2, n1_plus, n1_minus)

Thanks to akrun's answer I can build the following function:

my_fun <- function(dataf, V1, V2){
dataf %>%
dplyr::mutate("{{V1}}_{{V2}}" := paste0(format({{V1}}, big.mark   = ",") ,
  '\n(' , format({{V2}}, big.mark   = ",") , ')'))}

df<-df%>%my_fun(speed1, n1)

to create a new variable with a composite name as defined by"{{V1}}_{{V2}}" :=.

However, how were I to call a composite variable name on the right hand side of the equation? E.g. substituting format({{V2}}, big.mark = ",") with something like format('{{V2}}_plus', big.mark = ","). I tried (not working):

my_fun <- function(dataf, V1, V2){
dataf %>%
dplyr::mutate("{{V1}}_{{V2}}_plus" := paste0(format({{V1}}, big.mark   = ",") ,
  '\n(' , format('{{V2}}_plus', big.mark   = ",") , ')'))}

df<-df%>%my_fun(speed1, n1)

Desired output: I would expect a new column speed1_n1_plus that combines the values from speed1and n1_plus:

  string   speed1   speed2 n1 n2 n1_plus n1_minus       speed1_n1_plus
1    car 3958.415 1049.172 70 91      25       53 3,958.415\n(25)
2  train 6203.919 8639.160 52 92      14       91 6,203.919\n(14)
3   bike 2966.391 2997.303 35 55      46       61 2,966.391\n(46)
4  plain 2755.266 1627.379 98 66       8       49 2,755.266\n( 8)

I simply have to do operations on multiple variables with similar names. The variable names are composites of the 'core' name (in this case 'n1', {{V2}}) and suffixes and prefixes. I would like to avoid additional arguments for each variable name as it adds just a suffix to the core name.

I was trying: !!paste0, as.name(), eval(parse(text=), ..., which may work outside a function, but for me not within.


Solution

  • my_fun <- function(dataf, V1, V2){
               dataf %>%
                  dplyr::mutate("{{V1}}_{{V2}}_plus" := paste0(format({{V1}}, big.mark   = ","),
                      "\n(", format(!! rlang::sym(paste0(rlang::as_string(ensym(V2)), "_plus")), big.mark  = ","), ")"))}
    

    -testing

    df %>%
      my_fun(speed1, n1)
     string   speed1    speed2 n1 n2 n1_plus n1_minus  speed1_n1_plus
    1    car 4453.441 3336.7287 92 97      28       56 4,453.441\n(28)
    2  train 7718.381  638.5120 82 61       9       13 7,718.381\n( 9)
    3   bike 4648.093 4267.8390  7 92      83       29 4,648.093\n(83)
    4  plain 3815.145  793.6886 18 56      30       46 3,815.145\n(30)