gpt4 book ai didi

r - 简单子(monad)集/汇总函数的 dplyr'ish 方法

转载 作者:行者123 更新时间:2023-12-04 15:11:48 31 4
gpt4 key购买 nike

背景

提供的函数实现如下:

  • 使用用户提供的表达式子集提供的数据框
  • 选择所需的列
  • 对结果向量应用自定义汇总函数并返回标量

基础方法

summarise_filtered <-
function(df,
subset_arg,
summary_fun = c("min", "max", "median"),
select_col) {
summary_fun <- match.arg(summary_fun)

sbst_vals <-
subset.data.frame(
df,
subset = eval(parse(text = subset_arg)),
drop = TRUE,
select = eval(parse(text = select_col))
)

do.call(match.fun(summary_fun), list(sbst_vals))

}

结果

summarise_filtered(mtcars, "am == 1", "min", "cyl")
# [1] 4
summarise_filtered(mtcars, "am == 1", "max", "cyl")
# [1] 8

挑战

我有兴趣使用 dplyr 管道语法重写上面的函数。我的初步尝试满足了基本要求:

summarise_filtered_dplyrish <-
function(df,
subset_arg,
summary_fun,
select_col) {

df %>%
filter({{subset_arg}}) %>%
summarise(across(.cols = {{select_col}}, .fns = summary_fun)) %>%
pull({{select_col}})

}

调用时:

summarise_filtered_dplyrish(mtcars, am == 1, min, cyl)
# [1] 4

问题

我希望函数可以使用:

summarise_filtered_dplyrish(mtcars, "am == 1", "min", "cyl")

语法,除了已经工作的解决方案。这该怎么做?到目前为止,上面的调用产生了错误:

错误

Error: Problem with filter() input ..1. x Input ..1 must be alogical vector, not a character. ℹ Input ..1 is "am == 1". Runrlang::last_error() to see where the error occurred.

最佳答案

mincyl 可以通过 ensym() 轻松处理,它适用于字符串和符号。表达式 am == 1 需要做更多的工作。让我们定义一个仅当对象是字符串时才解析对象的辅助函数:

str2expr <- function(.x) {if( is.character(.x) ) rlang::parse_expr(.x) else .x}

我们现在可以捕获提供给 subset_arg 的参数并解析它(如果它是一个字符串):

summarise_filtered_dplyrish <-
function(df,
subset_arg,
summary_fun,
select_col) {

subset_expr <- rlang::enexpr(subset_arg) %>% str2expr()

df %>%
filter( !!subset_expr ) %>%
summarise(across(.cols = {{select_col}}, .fns = !!ensym(summary_fun))) %>%
pull( !!ensym(select_col) )
}

summarise_filtered_dplyrish( mtcars, am == 1, min, cyl ) # Works
summarise_filtered_dplyrish( mtcars, "am == 1", "min", "cyl" ) # Also works

简要说明:{{x}}!!enquo(x) 的简写,它捕获提供给函数参数的表达式以及应该评估该表达式的上下文。因为,您的上下文是由 df 有效定义的,所以可以将 enquo 放宽到 enexpr(捕获表达式但不捕获求值上下文)并且ensym(捕获符号或包含符号名称的字符串)。

关于r - 简单子(monad)集/汇总函数的 dplyr'ish 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65092760/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com