簡體   English   中英

通過 `...` 擴展 tidyverse function

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

我試圖通過允許用戶定義任意數量的 arguments 來代替...來擴展我的foo function。

這些... arguments 將完全被視為當前 3 arguments( timeoutcometrt_gr )。

這在 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

是的,這是可能的。 我們可以用省略號替換您的 arguments ...並允許 function 生成任意數量的帶有自定義列名的列。 這是 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

reprex package (v0.3.0) 創建於 2021-08-26

更新

回答評論中添加的問題。 是的,我們可以通過以下方式對上面的 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

reprex package (v0.3.0) 創建於 2021-08-26

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM