获取通过 R 中的管道传递的数据帧的名称

Get name of dataframe passed through pipe in R

我希望能够打印通过管道传递的数据帧的名称。这可能吗?我可以。

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

但是,它 returns "."当使用 magrittr 管道传输此函数时。

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

这在编写记录生产过程中使用的函数的自定义错误消息时会很有帮助——如果日志中只有“.”,则很难知道哪里出了问题。

return 原始调用可能就足够了,其中包括 mtcars %>% 部分。

这是第一次尝试,有点 hack,但似乎可行。

find_chain_parts <- function() {
    i <- 1
    while(!("chain_parts" %in% ls(envir=parent.frame(i))) && i < sys.nframe()) {
          i <- i+1
      }
    parent.frame(i)
}

printfirstname <- function(df){
    ee <- find_chain_parts()
    print(deparse(ee$lhs))
}

mtcars %>% printfirstname
# [1] "mtcars"

pipe 函数创建了一个跟踪链部件的环境。我尝试在当前执行环境中寻找这个变量,然后使用存储在那里的 lhs 信息在管道的开头找到符号。这没有经过很好的测试。

正如 Tom 和 Lionel Henry 对 MrFlick 的回答的评论,接受的答案在 more magrittr 2 下不再有效。

一个新的答案,然后,避开 deparse(substitute())sys.calls()。我从 Artem Sokolov 的回答中得到这个 。我不会假装完全理解发生了什么,但它对我有用:

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
}

对于管道和 non-piped 表示法都给出了所需的输出:

x_expression(mtcars)
# mtcars

mtcars %>% x_expression()
# mtcars