Skip to content

Commit

Permalink
Updated API for check_list_elements() (#131)
Browse files Browse the repository at this point in the history
**What changes are proposed in this pull request?**
- I started programming with this function in gtsummary, and it was
cumbersome to perform multi checks in one call to the function, and it
was more difficult to read. So I've updated the function to perform
checks on one named list at a time.

**Reference GitHub issue associated with pull request.** _e.g., 'closes
#1'_
closes #124


--------------------------------------------------------------------------------

Reviewer Checklist (if item does not apply, mark is as complete)

- [ ] Ensure all package dependencies are installed:
`devtools::install_dev_deps()`
- [ ] PR branch has pulled the most recent updates from master branch:
`usethis::pr_merge_main()`
- [ ] If a bug was fixed, a unit test was added.
- [ ] Run `pkgdown::build_site()`. Check the R console for errors, and
review the rendered website.
- [ ] Code coverage is suitable for any new functions/features:
`devtools::test_coverage()`
- [ ] `usethis::use_spell_check()` runs with no spelling errors in
documentation

When the branch is ready to be merged:
- [ ] Update `NEWS.md` with the changes from this pull request under the
heading "`# cards (development version)`". If there is an issue
associated with the pull request, reference it in parentheses at the end
update (see `NEWS.md` for examples).
- [ ] Increment the version number using `usethis::use_version(which =
"dev")`
- [ ] Run `usethis::use_spell_check()` again
- [ ] Approve Pull Request
- [ ] Merge the PR. Please use "Squash and merge".
  • Loading branch information
ddsjoberg authored Jan 30, 2024
1 parent d8cfb65 commit e0bd34f
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 49 deletions.
34 changes: 18 additions & 16 deletions R/ard_continuous.R
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,11 @@ ard_continuous <- function(data,
)

check_list_elements(
statistics = function(x) is.list(x) && is_named(x) && every(x, is.function),
x = statistics,
predicate = function(x) is.list(x) && is_named(x) && every(x, is.function),
error_msg =
list(
statistics =
c("Error in the argument {.arg {arg_name}} for variable {.val {variable}}.",
"i" = "Value must be a named list of functions."
)
c("Error in the argument {.arg {arg_name}} for variable {.val {variable}}.",
"i" = "Value must be a named list of functions."
)
)

Expand Down Expand Up @@ -152,7 +150,9 @@ ard_continuous <- function(data,
df_results |>
dplyr::mutate(context = "continuous") |>
tidy_ard_column_order() %>%
{structure(., class = c("card", class(.)))} # styler: off
{
structure(., class = c("card", class(.)))
}
}


Expand All @@ -163,7 +163,7 @@ ard_continuous <- function(data,
#' they do not begin with `"...ard_"` and end with `"..."`
#'
#' @param x data frame
#' @param env environment for error messaging
#' @param call frame for error messaging
#' @param exceptions character string of column names to exclude from checks
#'
#' @return invisible
Expand Down Expand Up @@ -293,19 +293,21 @@ ard_continuous <- function(data,
x[c("variable", "stat_name")] |>
dplyr::filter(.data$variable %in% .env$variable) |>
unique() %>%
{stats::setNames(as.list(.[["stat_name"]]), .[["stat_name"]])} # styler: off
{
stats::setNames(as.list(.[["stat_name"]]), .[["stat_name"]])
}

compute_formula_selector(
data = lst_stat_names,
x = enlst_arg
) %>%
# styler: off
{dplyr::tibble(
variable = variable,
stat_name = names(.),
"{new_column}" := unname(.)
)}
# styler: on
{
dplyr::tibble(
variable = variable,
stat_name = names(.),
"{new_column}" := unname(.)
)
}
}
) |>
dplyr::bind_rows()
Expand Down
46 changes: 23 additions & 23 deletions R/process_selectors.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@
#' - `compute_formula_selector()`: used in `process_formula_selectors()` to
#' evaluate a single argument.
#'
#' - `check_list_elements()`: accepts named arguments where the name is a list
#' that exists in the env, and the argument value is a predicate function
#' used to the values of the list.
#' - `check_list_elements()`: used to check the class/type/values of the list
#' elements, primarily those processed with `process_formula_selectors()`
#'
#' @param data (`data.frame`)\cr
#' a data frame
Expand All @@ -38,14 +37,18 @@
#' a function.
#' @param env (`environment`)\cr
#' env to save the results to. Default is the calling environment.
#' @param x ([`formula-list-selector`][syntax])\cr
#' a named list, list of formulas, or a single formula that will be
#' converted to a named list.
#' @param x
#' - `compute_formula_selector()`: ([`formula-list-selector`][syntax])\cr
#' a named list, list of formulas, or a single formula that will be
#' converted to a named list.
#' - `check_list_elements()`: (`named list`)\cr
#' a named list
#' @param predicate a predicate function that returns `TRUE` or `FALSE`
#' @param arg_name (`string`)\cr
#' a string with the argument named being processed. Used
#' in error messaging. Default is `caller_arg(x)`
#' @param error_msg (`character`)\cr
#' a named list where the list elements are strings that will
#' a character vector that will
#' be used in error messaging when mis-specified arguments are passed. Elements
#' `"{arg_name}"` and `"{variable}"` are available using glue syntax for messaging.
#' @param strict (`logical` scalar)\cr
Expand Down Expand Up @@ -220,23 +223,20 @@ compute_formula_selector <- function(data, x, arg_name = caller_arg(x), env = ca

#' @name process_selectors
#' @export
check_list_elements <- function(..., error_msg = list(), env = caller_env()) {
dots <- dots_list(...)

check_list_elements <- function(x,
predicate,
error_msg = NULL,
env = rlang::caller_env(),
arg_name = rlang::caller_arg(x)) {
imap(
dots,
function(predicate_fn, arg_name) {
imap(
get(arg_name, envir = env),
function(lst_element, variable) {
if (!isTRUE(predicate_fn(lst_element))) {
msg <-
error_msg[[arg_name]] %||%
"The value for argument {.arg {arg_name}} and variable {.val {variable}} is not the expected type."
cli::cli_abort(message = msg)
}
}
)
x,
function(lst_element, variable) {
if (!isTRUE(predicate(lst_element))) {
msg <-
error_msg %||%
"The value for argument {.arg {arg_name}} and variable {.val {variable}} is not the expected type."
cli::cli_abort(message = msg, call = env)
}
}
)

Expand Down
4 changes: 2 additions & 2 deletions man/dot-check_no_ard_columns.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 18 additions & 7 deletions man/process_selectors.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/testthat/_snaps/ard_continuous.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
Code
ard_continuous(mtcars, variables = "mpg", statistics = ~ list(mean = "this is a string"))
Condition
Error:
Error in `ard_continuous()`:
! Error in the argument `statistics` for variable "mpg".
i Value must be a named list of functions.

Expand Down

0 comments on commit e0bd34f

Please sign in to comment.