Reputation: 319
I'm trying to extend my foo
function below by allowing user to define any number of arguments in place of ...
.
These ...
arguments will exactly be treated as the current 3 arguments (time
, outcome
, trt_gr
).
Is this possible in 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
Upvotes: 1
Views: 76
Reputation: 18561
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. Here is such a function in the tidyverse style:
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)
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
:
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)
Upvotes: 4