在带有tidyeval的自制函数中选择函数

Dav*_*vid 3 r dplyr tidyeval rlang

因此,此示例基本上来自https://tidyeval.tidyverse.org/dplyr.html#patterns-for-single-arguments,它可以正常工作:

library(tidyverse)
group_mean <- function(df, group_var, summary_var){
  group_var <-  rlang::enquo(group_var)
  summary_var <-rlang::enquo(summary_var)

  name <- paste0(rlang::quo_name(summary_var), "_mean")

  df %>%
    dplyr::group_by(!!group_var) %>%
    dplyr::summarise(!!name := mean(!!summary_var, na.rm = TRUE))
}

mtcars %>% group_mean(group_var = cyl, summary_var = disp)
#> # A tibble: 3 x 2
#>     cyl disp_mean
#>   <dbl>     <dbl>
#> 1     4      105.
#> 2     6      183.
#> 3     8      353.
Run Code Online (Sandbox Code Playgroud)

我想例如能够有时选择中位数而不是均值,例如将函数名称更改为group_stat()

dyl*_*njm 5

你可以做这样的事情。我不太确定它是如何工作的,但是我已经在library(purrr)for 的源代码中看到了这种方法as_mapper()

https://github.com/tidyverse/purrr/blob/master/R/as_mapper.R

library(tidyverse)

group_stat <- function(df, group_var, summary_var, .f) {

    func <- rlang::as_closure(.f)

    group_var <-  rlang::enquo(group_var)
    summary_var <-rlang::enquo(summary_var)

    name <- paste0(rlang::quo_name(summary_var), "_", deparse(substitute(.f)))

    df %>%
        dplyr::group_by(!!group_var) %>%
        dplyr::summarise(!!name := func(!!summary_var, na.rm = TRUE))
}

mtcars %>% 
    group_stat(group_var = cyl, summary_var = disp, median)
#> # A tibble: 3 x 2
#>     cyl disp_median
#>   <dbl>       <dbl>
#> 1     4        108 
#> 2     6        168.
#> 3     8        350.

mtcars %>% 
    group_stat(group_var = cyl, summary_var = disp, mean)
#> # A tibble: 3 x 2
#>     cyl disp_mean
#>   <dbl>     <dbl>
#> 1     4      105.
#> 2     6      183.
#> 3     8      353.

mtcars %>% 
    group_stat(group_var = cyl, summary_var = disp, max)
#> # A tibble: 3 x 2
#>     cyl disp_max
#>   <dbl>    <dbl>
#> 1     4     147.
#> 2     6     258 
#> 3     8     472

mtcars %>% 
    group_stat(group_var = cyl, summary_var = disp, min)
#> # A tibble: 3 x 2
#>     cyl disp_min
#>   <dbl>    <dbl>
#> 1     4     71.1
#> 2     6    145  
#> 3     8    276.
Run Code Online (Sandbox Code Playgroud)

reprex软件包(v0.2.1)创建于2019-05-02

  • @aosmith出于某种原因,`as_name(enquo(.f))`在我的代码中不起作用。不确定为什么。也重新使用`as_closure()`,我认为还有`rlang :: as_function()`。像您一样,我不确定为什么这比直接使用function参数更好。 (2认同)