简体   繁体   English

通过 `...` 扩展 tidyverse function

[英]Extending a tidyverse function via `...`

I'm trying to extend my foo function below by allowing user to define any number of arguments in place of ... .我试图通过允许用户定义任意数量的 arguments 来代替...来扩展我的foo function。

These ... arguments will exactly be treated as the current 3 arguments ( time , outcome , trt_gr ).这些... arguments 将完全被视为当前 3 arguments( timeoutcometrt_gr )。

Is this possible in R?这在 R 中可能吗?

foo <- function(time = 1, outcome = 1, trt_gr = 1, ...){

  time <- seq_len(time)
  outcome <- seq_len(outcome)
  trt_gr <- seq_len(trt_gr)
  
data <- expand.grid(time = time, outcome = outcome, trt_gr = trt_gr, info. = c("control","treatment"))

data %>% 
  group_by(outcome, time, trt_gr) %>%
  summarise(info. = str_c(sort(info., decreasing = TRUE), 
                          collapse = ' vs. '), .groups = 'drop') 
}

# EXAMPLE OF CURRENT USE:

foo()

#  outcome  time trt_gr info.                
#    <int> <int>  <int> <chr>                
#1       1     1      1 treatment vs. control

Yes this is possible.是的,这是可能的。 We can replace your arguments with the elipsis ... and allow the function to produce any amount of columns of with custom column names.我们可以用省略号替换您的 arguments ...并允许 function 生成任意数量的带有自定义列名的列。 Here is such a function in the tidyverse style:这是 tidyverse 风格的 function:

library(tidyverse)

foo <- function(...){
  
  dots <- rlang::list2(...) 
  var_nms <- names(dots)
  inp <- purrr::map(dots, seq_len)

  data <- tidyr::expand_grid(!!! inp,
                             info. = c("control","treatment"))
  
  data %>% 
    dplyr::group_by(!!!syms(var_nms)) %>%
    dplyr::summarise(info. = stringr::str_c(sort(info., decreasing = TRUE), 
                                            collapse = ' vs. '), .groups = 'drop') 
}

foo(time = 1, outcome = 1, trt_gr = 1)
#> # A tibble: 1 x 4
#>    time outcome trt_gr info.                
#>   <int>   <int>  <int> <chr>                
#> 1     1       1      1 treatment vs. control

foo(some = 2, new = 1, colnames = 3)
#> # A tibble: 6 x 4
#>    some   new colnames info.                
#>   <int> <int>    <int> <chr>                
#> 1     1     1        1 treatment vs. control
#> 2     1     1        2 treatment vs. control
#> 3     1     1        3 treatment vs. control
#> 4     2     1        1 treatment vs. control
#> 5     2     1        2 treatment vs. control
#> 6     2     1        3 treatment vs. control

Created on 2021-08-26 by the reprex package (v0.3.0)reprex package (v0.3.0) 创建于 2021-08-26

Update更新

To answer the added question in the comments.回答评论中添加的问题。 Yes we can vectorize the function above in the following way which also allows to skip columns in a run, when they contain a 0 :是的,我们可以通过以下方式对上面的 function 进行矢量化,这也允许在运行中跳过包含0的列:

library(tidyverse)

foo <- function(...){
  
  dots <- rlang::list2(...) 
  var_nms <- names(dots)
  inp_ls <- map(dots, ~ map(.x, seq_len)) %>% transpose %>% map(compact)
  
  data_ls <- map(inp_ls, 
                 ~ tidyr::expand_grid(!!! .x,
                                      info. = c("control","treatment")))
  
  map2(data_ls, inp_ls, ~ .x %>% 
        dplyr::group_by(!!!syms(names(.y))) %>%
        dplyr::summarise(info. = stringr::str_c(sort(info., decreasing = TRUE), 
                                                collapse = ' vs. '), .groups = 'drop')) 
}

foo(some = c(1,2), new = c(1,0), colnames = c(1,3))
#> [[1]]
#> # A tibble: 1 x 4
#>    some   new colnames info.                
#>   <int> <int>    <int> <chr>                
#> 1     1     1        1 treatment vs. control
#> 
#> [[2]]
#> # A tibble: 6 x 3
#>    some colnames info.                
#>   <int>    <int> <chr>                
#> 1     1        1 treatment vs. control
#> 2     1        2 treatment vs. control
#> 3     1        3 treatment vs. control
#> 4     2        1 treatment vs. control
#> 5     2        2 treatment vs. control
#> 6     2        3 treatment vs. control

Created on 2021-08-26 by the reprex package (v0.3.0)reprex package (v0.3.0) 创建于 2021-08-26

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM