'Get name of dataframe passed through pipe in R

I would like to be able to print the name of a dataframe passed through the pipe. Is this possible? I can do.

printname <- function(df){
    print(paste(substitute(df)))
}
printname(mtcars)
#[1] "mtcars"

However, it returns "." when this function is piped using the magrittr pipe.

mtcars %>% printname
# [1] "."

This would be helpful when writing custom error messages of functions used in logged production processes -- it's hard to know where something failed if the only thing in the log is "."

It would probably be enough to return the original call, which would include the mtcars %>% piece.



Solution 1:[1]

As Tom & Lionel Henry commented on MrFlick's answer, the accepted answer no long works under more magrittr 2.

A new answer, then, eschews deparse(substitute()) for sys.calls(). I get this from Artem Sokolov's answer here. I won't pretend to fully understand what's happening but it works for me:

x_expression <- function(x) {
  getAST <- function(ee) purrr::map_if(as.list(ee), is.call, getAST)

  sc <- sys.calls()
  ASTs <- purrr::map( as.list(sc), getAST ) %>%
    purrr::keep( ~identical(.[[1]], quote(`%>%`)) )  # Match first element to %>%

  if( length(ASTs) == 0 ) return( enexpr(x) )        # Not in a pipe
  dplyr::last( ASTs )[[2]]    # Second element is the left-hand side
}

which gives the desired output, for both pipe and non-piped notation:

x_expression(mtcars)
# mtcars

mtcars %>% x_expression()
# mtcars

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Unrelated