用dplyr管道时获取lhs对象名称

Nic*_*cal 11 r pipe chain dplyr

我想要一个可以使用管道操作符从dplyr导出的函数.我没有使用magrittr.

df %>% my_function
Run Code Online (Sandbox Code Playgroud)

我如何获得df名称?如果我试试

my_function <- function(tbl){print(deparse(substitute(tbl)))}
Run Code Online (Sandbox Code Playgroud)

它返回

[1] "."
Run Code Online (Sandbox Code Playgroud)

虽然我想[1]"df"

有什么建议吗?

谢谢你在前进,
尼古拉

ger*_*sht 5

JBGruber在评论中链接到的 SO 答案主要解决了这个问题。它的工作原理是在执行环境中向上移动,直到找到某个变量,然后lhs从该环境返回。唯一缺少的是函数输出原始数据框的名称和操作数据的要求——我从 OP 的评论中收集了后一个要求。为此,我们只需要输出一个包含这些内容的列表,我们可以通过修改 MrFlick 的答案来实现:

get_orig_name <- function(df){
    i <- 1
    while(!("chain_parts" %in% ls(envir=parent.frame(i))) && i < sys.nframe()) {
        i <- i+1
    }
    list(name = deparse(parent.frame(i)$lhs), output = df)
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以运行get_orig_name到任何管道的末尾,以在列表中获取操作数据和原始数据框的名称。我们使用$

mtcars %>% summarize_all(mean) %>% get_orig_name

#### OUTPUT ####

$name
[1] "mtcars"

$output
       mpg    cyl     disp       hp     drat      wt     qsec     vs      am   gear   carb
1 20.09062 6.1875 230.7219 146.6875 3.596563 3.21725 17.84875 0.4375 0.40625 3.6875 2.8125
Run Code Online (Sandbox Code Playgroud)

我还应该提到,虽然我认为这个策略的细节很有趣,但我也认为它是不必要的复杂。听起来 OP 的目标是操作数据,然后将其写入与原始未操作数据帧同名的文件中,这可以使用更直接的方法轻松完成。例如,如果我们正在处理多个数据帧,我们可以执行以下操作:

df_list <- list(mtcars = mtcars, iris = iris)

for(name in names(df_list)){
    df_list[[name]] %>% 
        group_by_if(is.factor) %>%
        summarise_all(mean) %>% 
        write.csv(paste0(name, ".csv"))
}
Run Code Online (Sandbox Code Playgroud)

  • 我想过发布这个,但决定不发布,因为这个问题已经有几年了,并且在链接功能中没有太多可以增强的地方。我建议的两件事是废弃这部分 `&amp;&amp; i &lt; sys.nframe()` 因为它似乎永远不会变成 FALSE 并使用 `message(deparse(parent.frame(i)$lhs))` 来打印`return(df)` 之前的名称。我不会返回列表,因为进一步的管道会更加复杂。 (2认同)

cde*_*man -2

我认为如果不向您的my_function. 当用它链接函数时,dplyr会自动将 转换df为对象,因此在范围内使用tbl_df新名称以使管道更简单。"."dplyr

以下是 dplyr 的一种非常 hacky 的方法,它只添加一个附加参数来返回原始名称data.frame

my_function <- function(tbl, orig.df){print(deparse(substitute(orig.df)))}
df %>% my_function(df)
[1] "df"
Run Code Online (Sandbox Code Playgroud)

请注意,您不能仅将df与原始函数一起传递,因为该tbl_df对象会自动传递给所有后续函数。