Skip to content

Commit

Permalink
progress (#1595)
Browse files Browse the repository at this point in the history
  • Loading branch information
ddsjoberg authored Feb 4, 2024
1 parent b94919d commit 0ed6149
Show file tree
Hide file tree
Showing 13 changed files with 454 additions and 95 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Depends:
R (>= 4.1)
Imports:
broom.helpers,
cards (>= 0.0.0.9010),
cards (>= 0.0.0.9024),
cli (>= 3.6.1),
dplyr (>= 1.1.3),
glue (>= 1.6.2),
Expand All @@ -70,4 +70,4 @@ Encoding: UTF-8
Language: en-US
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
RoxygenNote: 7.3.1
2 changes: 1 addition & 1 deletion R/assign_summary_digits.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ assign_summary_digits <- function(data, statistic, type, digits = NULL) {
# if the passed value fully specifies the formatting for each 'statistic',
# then return it. Otherwise, the remaining stat will be filled below
if (setequal(statistic[[variable]], names(digits[[variable]]))) {
return(digits[[variable]])
return(lst_all_fmt_fns |> utils::modifyList(digits[[variable]]))
}
}

Expand Down
38 changes: 28 additions & 10 deletions R/assign_summary_type.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
#' Function inspects data and assigns a summary type when not specified
#' in the `type` argument.
#'
#' @param data a data frame
#' @param variables character vector of column names in `data`
#' @param value named list of values to show for dichotomous variables, where
#' the names are the variables
#' @param type named list of summary types, where names are the variables
#' @param data (`data.frame`)\cr
#' a data frame
#' @param variables (`character`)\cr
#' character vector of column names in `data`
#' @param value (`named list`)\cr
#' named list of values to show for dichotomous variables, where
#' the names are the variables
#' @param type (`named list`)\cr
#' named list of summary types, where names are the variables
#' @param cat_threshold (`integer`)\cr
#' for base R numeric classes with fewer levels than
#' this threshold will default to a categorical summary. Default is `10L`
#'
#' @return named list
#' @export
Expand All @@ -18,7 +25,7 @@
#' variables = c("age", "grade", "response"),
#' value = NULL
#' )
assign_summary_type <- function(data, variables, value, type = NULL) {
assign_summary_type <- function(data, variables, value, type = NULL, cat_threshold = 10L) {
# base classes that can be summarized as continuous
base_numeric_classes <- c("numeric", "integer", "difftime", "Date", "POSIXt", "double")

Expand All @@ -32,18 +39,29 @@ assign_summary_type <- function(data, variables, value, type = NULL) {
return(type[[variable]])
}

# if user supplied a dichotomous value, make it dichotomous
if (!is.null(.get_default_dichotomous_value(data[[variable]]))) {
return("dichotomous")
}

# factors and characters are categorical
if (inherits(data[[variable]], c("factor", "character"))) {
# factors are categorical
if (inherits(data[[variable]], "factor")) {
return("categorical")
}

# numeric variables with fewer than 10 levels will be categorical
# if all missing, the continuous
if (all(is.na(data[[variable]]))) {
return("continuous")
}

# characters are categorical
if (inherits(data[[variable]], "character")) {
return("categorical")
}

# numeric variables with fewer than 'cat_threshold' levels will be categorical
if (inherits(data[[variable]], base_numeric_classes) &&
length(unique(stats::na.omit(data[[variable]]))) < 10) {
length(unique(stats::na.omit(data[[variable]]))) < cat_threshold) {
return("categorical")
}

Expand Down
10 changes: 4 additions & 6 deletions R/modify_fmt_fun.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,14 @@ modify_fmt_fun <- function(x, update, rows = NULL) {
# converting update arg to a tidyselect list ---------------------------------
cards::process_formula_selectors(
data = x$table_body,
udpate = update
update = update
)
cards::check_list_elements(
check = function(x) is_function(x),
error_msg = list(
check = "The value passed in {.arg {arg_name}} for variable {.val {variable}} must be a function."
)
x = update,
predicate = function(x) is_function(x),
error_msg = "The value passed in {.arg {arg_name}} for variable {.val {variable}} must be a function."
)


# updating formatting functions ----------------------------------------------
x <-
modify_table_styling(
Expand Down
8 changes: 5 additions & 3 deletions R/modify_header.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ modify_header <- function(x, ..., text_interpret = c("md", "html"),

cards::process_formula_selectors(data = x$table_body, dots = dots)
cards::check_list_elements(
dots = function(x) is_string(x),
error_msg = list(dots = c("All values passed in {.arg ...} must be strings.",
"i" = "For example, {.code label = '**Variable**'}"))
x = dots,
predicate = function(x) is_string(x),
error_msg =
c("All values passed in {.arg ...} must be strings.",
"i" = "For example, {.code label = '**Variable**'}")
)

# evaluate the strings with glue
Expand Down
8 changes: 4 additions & 4 deletions R/select_helpers.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,27 @@ NULL
all_continuous <- function(continuous2 = TRUE) {
types <- if (continuous2) c("continuous", "continuous2") else "continuous"

where(function(x) attr(x, "gtsummary.type") %in% types)
where(function(x) isTRUE(attr(x, "gtsummary.type") %in% types))
}

#' @rdname select_helpers
#' @export
all_continuous2 <- function() {
where(function(x) attr(x, "gtsummary.type") %in% "continuous2")
where(function(x) isTRUE(attr(x, "gtsummary.type") %in% "continuous2"))
}

#' @rdname select_helpers
#' @export
all_categorical <- function(dichotomous = TRUE) {
types <- if (dichotomous) c("categorical", "dichotomous") else "categorical"

where(function(x) attr(x, "gtsummary.type") %in% types)
where(function(x) isTRUE(attr(x, "gtsummary.type") %in% types))
}

#' @rdname select_helpers
#' @export
all_dichotomous <- function() {
where(function(x) attr(x, "gtsummary.type") %in% "dichotomous")
where(function(x) isTRUE(attr(x, "gtsummary.type") %in% "dichotomous"))
}

# #' @rdname select_helpers
Expand Down
38 changes: 35 additions & 3 deletions R/standalone-checks.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#' @param x object whose class will be checked
#' @param class character vector or string indicating accepted classes.
#' Passed to `inherits(what=class)`
#' @param length if not `NULL`, the `x` object must be length specified
#' @param allow_empty logical indicating whether empty arguments are allowed.
#' Empty is defined by `rlang::is_empty()`, where empty elements include
#' `NULL`, `list()`, `character()`, etc. Default is `FALSE`
Expand All @@ -30,8 +31,15 @@
NULL

#' @rdname check_class
check_class <- function(x, class, allow_empty = FALSE,
check_class <- function(x, class, length = NULL, allow_empty = FALSE,
arg_name = rlang::caller_arg(x), call = rlang::caller_env()) {
if (isTRUE(allow_empty) && rlang::is_empty(x)) {
return(invisible())
}
if (!is.null(length)) {
check_length(x = x, length = length, arg_name = arg_name, call = call)
}

if (!inherits(x, class)) {
cli::cli_abort(
c("Argument {.arg {arg_name}} must be class {.cls {class}}.",
Expand All @@ -43,7 +51,7 @@ check_class <- function(x, class, allow_empty = FALSE,
}

#' @rdname check_class
check_class_data_frame <- function(x, arg_name = rlang::caller_arg(x), call = rlang::caller_env()) {
check_class_data_frame <- function(x, arg_name = rlang::caller_arg(x), call = parent.frame()) {
check_class(x = x, class = "data.frame", arg_name = arg_name, call = call)
}

Expand All @@ -53,9 +61,33 @@ check_class_data_frame <- function(x, arg_name = rlang::caller_arg(x), call = rl
#' @param arg_name string indicating the name of the argument. Used in the error messaging.
#' @inheritParams check_class
#' @keywords internal
check_not_missing <- function(x, arg_name = rlang::caller_arg(x), call = rlang::caller_env()) {
check_not_missing <- function(x, arg_name = rlang::caller_arg(x), call = parent.frame()) {
if (missing(x)) {
cli::cli_abort("The {.arg {arg_name}} argument cannot be missing.", call = call)
}
invisible()
}

#' Check Length
#'
#' @param msg (`string`)\cr
#' string passed to `cli::cli_abort(message=)`
#' @param length (`integer(1)`)\cr
#' integer specifying the required length
#' @inheritParams check_class
#' @keywords internal
#' @name check_length
NULL

#' @rdname check_length
check_length <- function(x, length, arg_name = caller_arg(x), call = parent.frame()) {
if (length(x) != length) {
cli::cli_abort("The {.arg {arg_name}} argument must be length {.val {length}}.", call = call)
}
invisible()
}

#' @rdname check_length
check_scalar <- function(x, arg_name = caller_arg(x), call = parent.frame()) {
check_length(x = x, length = 1L, arg_name = arg_name, call = call)
}
Loading

0 comments on commit 0ed6149

Please sign in to comment.