【问题标题】:Choosing the function in a selfmade function with tidyeval使用 tidyeval 在自制函数中选择函数
【发布时间】:2019-05-02 16:02:50
【问题描述】:

所以这个例子基本上来自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.

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

【问题讨论】:

    标签: r dplyr rlang tidyeval


    【解决方案1】:

    你可以做这样的事情。我不太确定这是如何工作的,但我在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.
    

    reprex package (v0.2.1) 于 2019 年 5 月 2 日创建

    【讨论】:

    • 我不确定您是否需要 rlang::as_closure() 步骤,尽管它可能有更好的地方。请参阅here 以查看直接使用函数参数代替函数的示例。另外,我最近才知道deparse(substitute(...)) 的“rlang”方法是rlang::as_name(enquo(...))。 :)
    • @aosmith 出于某种原因,as_name(enquo(.f)) 在我的代码中不起作用。不确定为什么会这样。也重新使用as_closure(),我认为还有rlang::as_function()。像你一样,我不确定为什么这可能比直接使用函数参数更好。
    • @aosmith & @dylanjm:但rlang::as_name(enquo(.f)) 没有,但我收到此消息:Error: Can't convert a function to a string
    • @aosmith:谢谢,我发布了一个新问题link。它更多是关于将功能与管道相结合......
    • @David 我根本看不出n() 在这种情况下如何工作,因为它不接受任何参数。也许你想要length()?但是,是的,如果在函数中不带参数设置 summarize(),则可以将 .f = nas_name() 一起使用。
    猜你喜欢
    • 2019-09-21
    • 2020-02-13
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 2019-09-26
    • 2020-05-31
    • 2021-08-14
    • 1970-01-01
    相关资源
    最近更新 更多