Search code examples
rdplyrmagrittrnse

How can I use dplyr/magrittr's pipe inside functions in R?


I'm trying to write a function which takes as argument a dataframe and the name of the function. When I try to write the function with the standard R syntax, I can get the good result using eval and substitute as recommanded by @hadley in http://adv-r.had.co.nz/Computing-on-the-language.html

> df <- data.frame(y = 1:10)
> f <- function(data, x) {
+   out <- mean(eval(expr = substitute(x), envir = data))
+   return(out)
+ }
> f(data = df, x = y)
[1] 5.5

Now, when I try to write the same function using the %>% operator, it doesn't work :

> df <- data.frame(y = 1:10)
> f <- function(data, x) {
+   data %>% 
+     eval(expr = substitute(x), envir = .) %>% 
+     mean()
+ }
> f(data = df, x = y)
Show Traceback
Rerun with Debug
 Error in eval(expr, envir, enclos) : objet 'y' introuvable 
> 

How can I using the combine the piping operator with the use of eval and substitute ? It's seems really tricky for me.


Solution

  • I've been trying to understand my problem.

    First, I've written what I want with the summarise() function :

    > library(dplyr)
    > df <- data.frame(y = 1:10)
    > summarise_(.data = df, mean = ~mean(y))
      mean
    1  5.5
    

    Then I try to program my own function. I've found a solution which seems to work with the lazyeval package in this post. I use the lazy() and the interp() functions to write what I want.

    The first possibility is here :

    > library(lazyeval)
    > f <- function(data, col) {
    +   col <- lazy(col)
    +   inter <- interp(~mean(x), x = col)
    +   summarise_(.data = data, mean = inter)    
    +   }
    > f(data = df, col = y)
      mean
    1  5.5
    

    I can also use pipes :

    > f <- function(data, col) {
    +   col <- lazy(col)
    +   inter <- interp(~mean(x), x = col)
    +   data %>% 
    +     summarise_(.data = ., mean = inter)    
    + }
    > 
    > f(data = df, col = y)
      mean
    1  5.5