Reputation: 111
Is what I'm doing bad practice? I can't find anything specific to this topic, tidyeval docs don't mention it.
Writing a function that takes in a tibble, filtering parameters, grouping parameters and returns a summarized tibble.
createTable <- function(counts, mapper = NULL,day = NULL, week = NULL, month = NULL, ...){
# Check for optional param
day_missing <- is.null(day)
print(day_missing)
month_missing <- is.null(month)
week_missing <- is.null(week)
mapper_missing <- is.null(mapper)
# reassigns input params to new vars for use with dplyr::filter
m <- month
d <- day
w <- week
mp <- mapper
# group, summarise, filter and score counts
group_vars <- enquos(...)
counts %>% # counts is always in the same format, which allows for the below filtering
group_by(!!!group_vars) %>%
summarise_at(summaryVars, sum) %>% # summaryVars is a global var, always the same variables being summed
filter(if(month_missing) TRUE else month == m) %>%
filter(if(week_missing) TRUE else week == w) %>%
filter(if(day_missing) TRUE else day == d) %>%
filter(if(mapper_missing) TRUE else mapper == mp) %>%
calcScores() # calcScores is a global function, it converts the summarised data above into scored data (e.g. count of 10 = scored as 250)
}
This does exactly what I need it to do, but only if all parameters are supplied implicitly
test <- createTable(featureCounts2019, "mcglonee", NULL, NULL, 5, mapper, month, week)
#> Get expected output
test <- createTable(counts = featureCounts2019, mapper = "mcglonee", month = 5, mapper, month, week)
#> This won't work, R won't know what to do with the group_vars
I thought about supplying the group_vars as a list and then unlisting into enquos, but that throws me an error saying that objects in the list don't exist.
createTable2 <- function(counts, mapper = NULL,day = NULL, week = NULL, month = NULL, group_vars){
# Check for optional param
day_missing <- is.null(day)
month_missing <- is.null(month)
week_missing <- is.null(week)
mapper_missing <- is.null(mapper)
# reassigns input params to new vars for use with dplyr::filter
m <- month
d <- day
w <- week
mp <- mapper
group_vars <- unlist(group_vars)
# group, summarise, filter and score counts
group_vars <- enquos(group_vars)
counts %>% # counts is always in the same format, which allows for the below filtering
group_by(!!!group_vars) %>%
summarise_at(summaryVars, sum) %>% # summaryVars is a global var, always the same variables being summed
filter(if(month_missing) TRUE else month == m) %>%
filter(if(week_missing) TRUE else week == w) %>%
filter(if(day_missing) TRUE else day == d) %>%
filter(if(mapper_missing) TRUE else mapper == mp) %>%
calcScores() # calcScores is a global function, it converts the summarised data above into scored data (e.g. count of 10 = scored as 250)
}
test2 <- createTable2(counts = featureCounts2019, mapper = "mcglonee", month = 5, group_vars = list(mapper, month, week))
#> Error in unlist(group_vars) : object 'mapper' not found
Not the end of the world since this funciton is just for me, but what if I am writing something as part of a package I think people will use, what then? How are you able to have both optional parameters and use tidydots?
Upvotes: 3
Views: 110
Reputation: 167
Your example is a little convoluted, but I think the Tidyverse design principles suggest a simple solution: place dots between your data argument and detail arguments like so:
createTable <- function(counts, ..., mapper = NULL,
day = NULL, week = NULL, month = NULL) {
# function body
}
As per design principles:
this forces the user of your function to fully name the detail arguments, because arguments that come after ... are never matched by position or partially by name
Additionally, you can check explicitly for missing function arguments with missing()
.
Upvotes: 1