使用dplyr进行管道传递时获取对象名称

问题描述 投票:11回答:4

我想拥有一个可以使用从dplyr导出的管道运算符的函数。我没有使用magrittr。

df %>% my_function

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

my_function <- function(tbl){print(deparse(substitute(tbl)))}

返回

[1] "."

而我想拥有[1]“ df”

有任何建议吗?

谢谢你,尼古拉

r pipe dplyr chain
4个回答
2
投票

这是一种骇人听闻的方法,我敢肯定,在很多情况下,这种方法会被打破:

library(data.table) # for the address function
                    # or parse .Internal(inspect if you feel masochistic

fn = function(tbl) {
  objs = ls(parent.env(environment()))
  objs[sapply(objs,
          function(x) address(get(x, env = parent.env(environment()))) == address(tbl))]
}

df = data.frame(a = 1:10)
df %>% fn
#[1] "df"

2
投票

注释中的JBGruber links to大部分解决了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)
}

现在我们可以将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

我还应该提到,尽管我认为该策略的细节很有趣,但我也认为它不必要地复杂。听起来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"))
}

0
投票

受到gersht提到的Link的启发。

您可以返回5代以获得名称,答案如下:

library(dplyr)

a <- 1

df1 <- data.frame(a = 1:10)

df2 <- data.frame(a = 1:10)

a %>% {parent.frame(5)$lhs}

df1 %>% {parent.frame(5)$lhs}

df2 %>% {parent.frame(5)$lhs}

-1
投票

我相信,如果不向您的my_function添加额外的参数,这是不可能的。当使用dplyr链接功能时,它会自动将df转换为tbl_df对象,因此在"."范围内使用了新名称dplyr以简化管道。

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.