Search code examples
rmagrittr

How to write custom pipe-friendly functions?


I'm trying to create pipe-friendly functions using magrittr

For example, I tried to write a custom function to calculate the mean of a column:

library(magrittr)
custom_function <-
  function(.data, x) {
   mean(.data$x)
  }

mtcars %>%
 custom_function(mpg)

But I'm getting this error:

Error in (function(x, i, exact) if (is.matrix(i)) as.matrix(x)[[i]] else .subset2(x,  : 
  object 'mpg' not found

Maybe my reference to the variable is not working. How do I fix this .data$x ?


Solution

  • In base R, we can change the $ to [[ and convert the unquoted column names to character with deparse/substitute

    custom_function <- function(.data, x) {
      mean(.data[[deparse(substitute(x))]])
     }
    

    Now, we apply the function

    mtcars %>%
      custom_function(mpg)
    #[1] 20.09062
    

    The issue with $ is that it is literally checking the column name 'x' without the associative value it stored. Thus, it is failing and returns NULL


    With tidyverse, we can use the curly-curly operator ({{}}) to do the evaluation within summarise. As we need only a single summarised output, summarise can return that single value whereas if we need to create a new column in the original dataset, we need mutate. After we create summarised column, just pull that column as a vector

    custom_function <- function(.data, x) {
         .data %>%
             summarise(out = mean({{x}})) %>%
             pull(out)
    }
    
    mtcars %>% 
       custom_function(mpg)
    [1] 20.09062