rdataframefunction

Performing operations inside a function on dataframe with pipe workflow


I have the following dataframe:

df <- data.frame(ID=1:3, col1=1:3, col2=4:6, col3=7:9, col4=10:12, col5=13:15, col6=16:18, col7=19:21)

I need to create a function that essentially does the following:

 df_new <- df %>% select(ID, c(col1:col5)) %>% mutate(col1=col1/col2, col3=col3/col2, col4=-col4, col5=-col5)

With the result:

> df_new
  ID col1 col2 col3 col4 col5
1  1 0.25    4 1.75  -10  -13
2  2 0.40    5 1.60  -11  -14
3  3 0.50    6 1.50  -12  -15

I write a function to do this:

genUIR_test = function(df, arg1, arg2, arg3, arg4, arg5){
  
  arg1 <- substitute(arg1)
  arg2 <- substitute(arg2)
  arg3 <- substitute(arg3)
  arg4 <- substitute(arg4)
  arg5 <- substitute(arg5)
  
  df_new = df %>% select(ID, c(arg1:arg5)) %>% 
  mutate(arg1=arg1/arg2, arg3=arg3/arg2, arg4=-arg4, arg5=-arg5)
  
  return(df_new)
  
}

And when I run the function, I get the following error:

> genUIR_test(df, col1, col2, col3, col4, col5)
Error in `mutate()`:
ℹ In argument: `arg1 = arg1/arg2`.
Caused by error in `arg1 / arg2`:
! non-numeric argument to binary operator
Run `rlang::last_trace()` to see where the error occurred.

Can you please tell me what I am doing wrong? Thanks.


Solution

  • substitute is the base R way of non-standard evaluation, the tidyverse way is with {{.
    And to assign to names passed as arguments to a mutate statement, use :=.

    suppressPackageStartupMessages({
      library(dplyr)
    })
    
    genUIR_test <- function(df, arg1, arg2, arg3, arg4, arg5){
    
      df_new <- df %>% 
        select(ID, {{arg1}}:{{arg5}}) %>%
        mutate(
          {{arg1}} := {{arg1}} / {{arg2}},
          {{arg3}} := {{arg3}} / {{arg2}},
          {{arg4}} := -{{arg4}},
          {{arg5}} := -{{arg5}}
        )
      df_new
    }
    
    df <- data.frame(
      ID=1:3, 
      col1=1:3, col2=4:6, col3=7:9, 
      col4=10:12, col5=13:15, col6=16:18, 
      col7=19:21
    )
    
    genUIR_test(df, col1, col2, col3, col4, col5)
    #>   ID col1 col2 col3 col4 col5
    #> 1  1 0.25    4 1.75  -10  -13
    #> 2  2 0.40    5 1.60  -11  -14
    #> 3  3 0.50    6 1.50  -12  -15
    

    Created on 2025-07-12 with reprex v2.1.1