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"
有什么建议吗?
谢谢你在前进,
尼古拉
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)
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对象会自动传递给所有后续函数。