get lhs object name when piping with dplyr

后端 未结 5 2231
遥遥无期
遥遥无期 2021-02-13 15:43

I\'d like to have a function that can use pipe operator as exported from dplyr. I am not using magrittr.

df %>% my_function

How can I get df

5条回答
  •  耶瑟儿~
    2021-02-13 16:12

    Although the question is an old one, and the bounty has already been awarded, I would like to extend on gersht's excellent answer which works perfectly fine for getting the most lefthand-side object name. However, integrating this functionality in a dplyr workflow is not yet solved, apart from using this approach in the very last step of a pipe.

    Since I'm using dplyr a lot, I have created a group of custom wrapper functions around the common dplyr verbs which I call metadplyr (I'm still playing around with the functionality, which is why I haven't uploaded it on github yet).

    In essence, those functions create a new class called meta_tbl on top of a tibble and write certain things in the attributes of that object. Applied to the problem of the OP I provide a simple example with filter, but the procedure works on any other dplyr verb as well.

    In my original function family I use slightly different names than dplyr, but the approach also works when 'overwriting' the original dplyr verbs.

    Below is a new filter function which turns a data frame or tibble into a meta_tbl and writes the original name of the lhs object into the attribute .name. Here I am using a short version of gersht's approach.

    library(dplyr)
    
     filter <- function(.data, ...) {
    
        if(!("meta_tbl" %in% class(.data))) {
    
          .data2 <- as_tibble(.data)
    
          # add new class 'meta_tbl' to data.frame  
          attr(.data2, "class") <- c(attr(.data2, "class"), "meta_tbl")
    
          # write lhs original name into attributes
          i <- 1
          while(!("chain_parts" %in% ls(envir=parent.frame(i)))) {
            i <- i+1
          }
          attr(.data2, ".name") <- deparse(parent.frame(i)$lhs)
    
        }
    
        dplyr::filter(.data2, ...)
    
    }
    

    For convenience it is good to have some helper function to extract the original name from the attributes easily.

    .name <- function(.data) {
      if("meta_tbl" %in% class(.data)) {
      attr(.data, ".name")
      } else stop("this function only work on objects of class 'meta_tbl'")
    
    }
    

    Both functions can be used in a workflow in the following way:

    mtcars %>% 
      filter(gear == 4) %>% 
      write.csv(paste0(.name(.), ".csv"))
    

    This might be a bad example, since the pipe doesn't continue, but in theory, we could use this pipe including the original name and pipe it in further function calls.

提交回复
热议问题