From bc15eb38f698e5fa38c7d64089d891afa313667a Mon Sep 17 00:00:00 2001 From: Emil Hvitfeldt Date: Wed, 15 Nov 2023 18:09:44 -0800 Subject: [PATCH 1/5] remove abort in validation.R --- R/prob-binary-thresholds.R | 4 +- R/prob-classification_cost.R | 6 +- R/validation.R | 247 +++++++++--------- tests/testthat/_snaps/aaa-metrics.md | 4 +- tests/testthat/_snaps/check_metric.md | 14 +- tests/testthat/_snaps/conf_mat.md | 24 +- tests/testthat/_snaps/error-handling.md | 16 +- tests/testthat/_snaps/fair-aaa.md | 4 +- .../_snaps/prob-classification_cost.md | 6 +- tests/testthat/_snaps/prob-gain_curve.md | 2 +- tests/testthat/_snaps/prob-lift_curve.md | 2 +- tests/testthat/_snaps/template.md | 10 +- tests/testthat/_snaps/validation.md | 48 ++-- 13 files changed, 199 insertions(+), 188 deletions(-) diff --git a/R/prob-binary-thresholds.R b/R/prob-binary-thresholds.R index 9f89074c..e718722b 100644 --- a/R/prob-binary-thresholds.R +++ b/R/prob-binary-thresholds.R @@ -17,7 +17,7 @@ binary_threshold_curve <- function(truth, if (!is.factor(truth)) { cli::cli_abort( - "{.arg truth} must be a factor, not {.obj_friendly_type {truth}}.", + "{.arg truth} must be a factor, not {.obj_type_friendly {truth}}.", .internal = TRUE ) } @@ -29,7 +29,7 @@ binary_threshold_curve <- function(truth, } if (!is.numeric(estimate)) { cli::cli_abort( - "{.arg estimate} must be numeric, not {.obj_friendly_type {estimate}}.", + "{.arg estimate} must be numeric, not {.obj_type_friendly {estimate}}.", .internal = TRUE ) } diff --git a/R/prob-classification_cost.R b/R/prob-classification_cost.R index 7042e83b..31e0db0b 100644 --- a/R/prob-classification_cost.R +++ b/R/prob-classification_cost.R @@ -244,7 +244,7 @@ validate_costs <- function(costs, levels) { if (!is.character(costs$truth)) { cli::cli_abort( "{.code costs$truth} must be a character or factor column, \\ - not {.obj_friendly_type {costs$truth}}." + not {.obj_type_friendly {costs$truth}}." ) } @@ -254,14 +254,14 @@ validate_costs <- function(costs, levels) { if (!is.character(costs$estimate)) { cli::cli_abort( "{.code costs$estimate} must be a character or factor column, \\ - not {.obj_friendly_type {costs$estimate}}." + not {.obj_type_friendly {costs$estimate}}." ) } if (!is.numeric(costs$cost)) { cli::cli_abort( "{.code costs$cost} must be a numeric column, \\ - not {.obj_friendly_type {costs$cost}}." + not {.obj_type_friendly {costs$cost}}." ) } diff --git a/R/validation.R b/R/validation.R index d9e01dc2..ad898e20 100644 --- a/R/validation.R +++ b/R/validation.R @@ -2,39 +2,44 @@ validate_numeric_truth_numeric_estimate <- function(truth, estimate, call = caller_env()) { if (!is.numeric(truth)) { - cls <- class(truth)[[1]] - abort(paste0( - "`truth` should be a numeric, not a `", cls, "`." - ), call = call) + cli::cli_abort( + "{.arg truth} should be a numeric, \\ + not {.obj_type_friendly {truth}}.", + call = call + ) } if (!is.numeric(estimate)) { - cls <- class(estimate)[[1]] - abort(paste0( - "`estimate` should be a numeric, not a `", cls, "`." - ), call = call) + cli::cli_abort( + "{.arg estimate} should be a numeric, \\ + not {.obj_type_friendly {estimate}}.", + call = call + ) } if (is.matrix(estimate)) { - abort(paste0( - "`estimate` should be a numeric vector, not a numeric matrix." - ), call = call) + cli::cli_abort( + "{.arg estimate} should be a numeric vector, not a numeric matrix.", + call = call + ) } if (is.matrix(truth)) { - abort(paste0( - "`truth` should be a numeric vector, not a numeric matrix." - ), call = call) + cli::cli_abort( + "{.arg truth} should be a numeric vector, not a numeric matrix.", + call = call + ) } n_truth <- length(truth) n_estimate <- length(estimate) if (n_truth != n_estimate) { - abort(paste0( - "Length of `truth` (", n_truth, ") ", - "and `estimate` (", n_estimate, ") must match." - ), call = call) + cli::cli_abort( + "{.arg truth} ({n_truth}) and \\ + {.arg estimate} ({n_estimate}) must be the same length.", + call = call + ) } } @@ -42,30 +47,30 @@ validate_factor_truth_factor_estimate <- function(truth, estimate, call = caller_env()) { if (!is.factor(truth)) { - cls <- class(truth)[[1]] - abort(paste0( - "`truth` should be a factor, not a `", cls, "`." - ), call = call) + cli::cli_abort( + "{.arg truth} should be a factor, \\ + not a {.obj_type_friendly {truth}}.", + call = call + ) } if (!is.factor(estimate)) { - cls <- class(estimate)[[1]] - abort(paste0( - "`estimate` should be a factor, not a `", cls, "`." - ), call = call) + cli::cli_abort( + "{.arg estimate} should be a factor, \\ + not a {.obj_type_friendly {estimate}}.", + call = call + ) } lvls_t <- levels(truth) lvls_e <- levels(estimate) if (!identical(lvls_t, lvls_e)) { - lvls_t <- paste0(lvls_t, collapse = ", ") - lvls_e <- paste0(lvls_e, collapse = ", ") - abort( - paste0( - "`truth` and `estimate` levels must be equivalent.\n", - "`truth`: ", lvls_t, "\n", - "`estimate`: ", lvls_e, "\n" + cli::cli_abort( + c( + "x" = "{.arg truth} and {.arg estimate} levels must be equivalent.", + "*" = "{.arg truth}: {lvls_t}.", + "*" = "{.arg estimate}: {lvls_e}." ), call = call ) @@ -75,11 +80,9 @@ validate_factor_truth_factor_estimate <- function(truth, n_estimate <- length(estimate) if (n_truth != n_estimate) { - abort( - paste0( - "Length of `truth` (", n_truth, ") ", - "and `estimate` (", n_estimate, ") must match." - ), + cli::cli_abort( + "{.arg truth} ({n_truth}) and \\ + {.arg estimate} ({n_estimate}) must be the same length.", call = call ) } @@ -90,32 +93,37 @@ validate_factor_truth_matrix_estimate <- function(truth, estimator, call = caller_env()) { if (!is.factor(truth)) { - cls <- class(truth)[[1]] - abort(paste0( - "`truth` should be a factor, not a `", cls, "`." - ), call = call) + cli::cli_abort( + "{.arg truth} should be a factor, \\ + not a {.obj_type_friendly {truth}}.", + call = call + ) } if (estimator == "binary") { if (is.matrix(estimate)) { - abort(paste0( - "You are using a binary metric but have passed multiple columns to `...`." - ), call = call) + cli::cli_abort( + "You are using a binary metric but have passed multiple columns to \\ + {.arg ...}.", + call = call + ) } if (!is.numeric(estimate)) { - cls <- class(estimate)[[1]] - abort(paste0( - "`estimate` should be a numeric vector, not a `", cls, "` vector." - ), call = call) + cli::cli_abort( + "{.arg estimate} should be a numeric vector, \\ + not {.obj_type_friendly {estimate}}.", + call = call + ) } n_lvls <- length(levels(truth)) if (n_lvls != 2) { - abort(paste0( - "`estimator` is binary, only two class `truth` factors are allowed. ", - "A factor with ", n_lvls, " levels was provided." - ), call = call) + cli::cli_abort( + "{.arg estimator} is binary, only two class {.arg truth} factors are \\ + allowed. A factor with {n_lvls} levels was provided.", + call = call + ) } } else { n_lvls <- length(levels(truth)) @@ -125,19 +133,21 @@ validate_factor_truth_matrix_estimate <- function(truth, n_cols <- 1L } - if (n_lvls != n_cols) { - abort(paste0( - "The number of levels in `truth` (", n_lvls, ") ", - "must match the number of columns supplied in `...` (", n_cols, ")." - ), call = call) + cli::cli_abort( + "The number of levels in `truth` ({n_lvls}) \\ + must match the number of columns supplied in `...` ({n_cols}).", + call = call + ) } if (!is.numeric(as.vector(estimate))) { - cls <- class(as.vector(estimate))[[1]] - abort(paste0( - "The columns supplied in `...` should be numerics, not `", cls, "`s." - ), call = call) + cls <- as.vector(estimate) + cli::cli_abort( + "The columns supplied in {.arg ...} should be numerics, \\ + not {.cls cls}.", + call = call + ) } } } @@ -146,21 +156,26 @@ validate_surv_truth_list_estimate <- function(truth, estimate, call = caller_env()) { if (!inherits(truth, "Surv")) { - cls <- class(truth)[[1]] - abort(paste0( - "`truth` should be a Surv object, not a `", cls, "`." - ), call = call) + cli::cli_abort( + "`truth` should be a Surv object, \\ + not a {.obj_type_friendly {truth}}.", + call = call + ) } if (!is.list(estimate)) { - cls <- class(estimate)[[1]] - abort(paste0( - "`estimate` should be a list, not a `", cls, "`." - ), call = call) + cli::cli_abort( + "{.arg estimate} should be a list, \\ + not a {.obj_type_friendly {estimate}}.", + call = call + ) } if (!all(vapply(estimate, is.data.frame, FUN.VALUE = logical(1)))) { - abort("All elements of `estimate` should be data.frames.", call = call) + cli::cli_abort( + "All elements of {.arg estimate} should be data.frames.", + call = call + ) } valid_names <- c(".eval_time", ".pred_survival", ".weight_censored") @@ -171,20 +186,22 @@ validate_surv_truth_list_estimate <- function(truth, ) if (!all(has_names)) { - abort(paste0( - "All data.frames of `estimate` should include column names: ", - "`.eval_time`, `.pred_survival`, and `.weight_censored`." - ), call = call) + cli::cli_abort( + "All data.frames of {.arg estimate} should include column names: \\ + {.field (.eval_time)}, {.field (.pred_survival)}, and \\ + {.field (.weight_censored)}.", + call = call) } n_truth <- nrow(truth) n_estimate <- length(estimate) if (n_truth != n_estimate) { - abort(paste0( - "Length of `truth` (", n_truth, ") ", - "and `estimate` (", n_estimate, ") must match." - ), call = call) + cli::cli_abort( + "{.arg truth} ({n_truth}) and \\ + {.arg estimate} ({n_estimate}) must be the same length.", + call = call + ) } } @@ -192,33 +209,36 @@ validate_surv_truth_numeric_estimate <- function(truth, estimate, call = caller_env()) { if (!.is_surv(truth, fail = FALSE)) { - cls <- class(truth)[[1]] - abort(paste0( - "`truth` should be a Surv object, not a `", cls, "`." - ), call = call) + cli::cli_abort( + "{.arg truth} should be a Surv object, \\ + not {.obj_type_friendly {truth}}.", + call = call) } if (!is.numeric(estimate)) { - cls <- class(estimate)[[1]] - abort(paste0( - "`estimate` should be a numeric, not a `", cls, "`." - ), call = call) + cli::cli_abort( + "{.arg estimate} should be a numeric, \\ + not {.obj_type_friendly {estimate}}.", + call = call + ) } if (is.matrix(estimate)) { - abort(paste0( - "`estimate` should be a numeric vector, not a numeric matrix." - ), call = call) + cli::cli_abort( + "{.arg estimate} should be a numeric vector, not a numeric matrix.", + call = call + ) } n_truth <- nrow(truth) n_estimate <- length(estimate) if (n_truth != n_estimate) { - abort(paste0( - "Length of `truth` (", n_truth, ") ", - "and `estimate` (", n_estimate, ") must match." - ), call = call) + cli::cli_abort( + "{.arg truth} ({n_truth}) and \\ + {.arg estimate} ({n_estimate}) must be the same length.", + call = call + ) } } @@ -229,10 +249,11 @@ validate_binary_estimator <- function(truth, estimator, call = caller_env()) { lvls <- levels(truth) if (length(lvls) != 2) { - abort(paste0( - "`estimator` is binary, only two class `truth` factors are allowed. ", - "A factor with ", length(lvls), " levels was provided." - ), call = call) + cli::cli_abort( + "{.arg estimator} is binary, only two class {.arg truth} factors are \\ + allowed. A factor with {length(lvls)} levels was provided.", + call = call + ) } } @@ -260,26 +281,15 @@ validate_estimator <- function(estimator, allowed <- c("binary", "macro", "micro", "macro_weighted") } - if (length(estimator) != 1) { - abort(paste0( - "`estimator` must be length 1, not ", length(estimator), "." - ), call = call) - } - - if (!is.character(estimator)) { - abort(paste0( - "`estimator` must be a character, not a ", class(estimator)[1], "." - ), call = call) - } + check_string(estimator, call = call) estimator_ok <- (estimator %in% allowed) if (!estimator_ok) { - allowed <- paste0(dQuote(allowed), collapse = ", ") - abort(paste0( - "`estimator` must be one of: ", allowed, - ". Not ", dQuote(estimator), "." - ), call = call) + cli::cli_abort( + "{.arg estimator} must be one of: {allowed}, not {estimator}.", + call = call + ) } } @@ -291,10 +301,11 @@ validate_case_weights <- function(case_weights, size, call = caller_env()) { size_case_weights <- length(case_weights) if (size_case_weights != size) { - abort(paste0( - "`case_weights` (", size_case_weights, ") must have the same ", - "length as `truth` (", size, ")." - ), call = call) + cli::cli_abort( + "{.arg truth} ({size}) and \\ + {.arg case_weights} ({size_case_weights}) must be the same length.", + call = call + ) } invisible() diff --git a/tests/testthat/_snaps/aaa-metrics.md b/tests/testthat/_snaps/aaa-metrics.md index e931a217..6d54421f 100644 --- a/tests/testthat/_snaps/aaa-metrics.md +++ b/tests/testthat/_snaps/aaa-metrics.md @@ -6,7 +6,7 @@ Error in `metric_set()`: ! Failed to compute `accuracy()`. Caused by error: - ! `estimate` should be a factor, not a `numeric`. + ! `estimate` should be a factor, not a a double vector. --- @@ -16,7 +16,7 @@ Error in `metric_set()`: ! Failed to compute `rmse()`. Caused by error: - ! `estimate` should be a numeric, not a `factor`. + ! `estimate` should be a numeric, not a object. --- diff --git a/tests/testthat/_snaps/check_metric.md b/tests/testthat/_snaps/check_metric.md index 1fc315e4..8a4df203 100644 --- a/tests/testthat/_snaps/check_metric.md +++ b/tests/testthat/_snaps/check_metric.md @@ -4,7 +4,7 @@ check_numeric_metric(1:10, 1:10, 1:11) Condition Error: - ! `case_weights` (11) must have the same length as `truth` (10). + ! `truth` (10) and `case_weights` (11) must be the same length. # check_numeric_metric() validates inputs @@ -12,7 +12,7 @@ check_numeric_metric(1, "1", 1) Condition Error: - ! `estimate` should be a numeric, not a `character`. + ! `estimate` should be a numeric, not a string. # check_class_metric() validates case_weights @@ -20,7 +20,7 @@ check_class_metric(letters, letters, 1:5) Condition Error: - ! `case_weights` (5) must have the same length as `truth` (26). + ! `truth` (26) and `case_weights` (5) must be the same length. # check_class_metric() validates inputs @@ -28,7 +28,7 @@ check_class_metric(1, "1", 1) Condition Error: - ! `truth` should be a factor, not a `numeric`. + ! `truth` should be a factor, not a a number. # check_class_metric() validates estimator @@ -46,7 +46,7 @@ estimator = "binary") Condition Error: - ! `case_weights` (4) must have the same length as `truth` (3). + ! `truth` (3) and `case_weights` (4) must be the same length. # check_prob_metric() validates inputs @@ -64,7 +64,7 @@ .pred_survival, case_weights = 1:151) Condition Error: - ! `case_weights` (151) must have the same length as `truth` (228). + ! `truth` (228) and `case_weights` (151) must be the same length. # check_static_survival_metric() validates inputs @@ -73,5 +73,5 @@ lung_surv$inst), case_weights = 1:150) Condition Error: - ! `case_weights` (150) must have the same length as `truth` (228). + ! `truth` (228) and `case_weights` (150) must be the same length. diff --git a/tests/testthat/_snaps/conf_mat.md b/tests/testthat/_snaps/conf_mat.md index cbf402a9..753eb450 100644 --- a/tests/testthat/_snaps/conf_mat.md +++ b/tests/testthat/_snaps/conf_mat.md @@ -41,9 +41,9 @@ conf_mat(three_class, truth = obs_rev, estimate = pred, dnn = c("", "")) Condition Error in `conf_mat()`: - ! `truth` and `estimate` levels must be equivalent. - `truth`: virginica, versicolor, setosa - `estimate`: setosa, versicolor, virginica + x `truth` and `estimate` levels must be equivalent. + * `truth`: virginica, versicolor, and setosa. + * `estimate`: setosa, versicolor, and virginica. --- @@ -51,9 +51,9 @@ conf_mat(three_class, truth = onelevel, estimate = pred, dnn = c("", "")) Condition Error in `conf_mat()`: - ! `truth` and `estimate` levels must be equivalent. - `truth`: 1 - `estimate`: setosa, versicolor, virginica + x `truth` and `estimate` levels must be equivalent. + * `truth`: 1. + * `estimate`: setosa, versicolor, and virginica. --- @@ -69,9 +69,9 @@ conf_mat(three_class, truth = obs_rev, estimate = pred, dnn = c("", "")) Condition Error in `conf_mat()`: - ! `truth` and `estimate` levels must be equivalent. - `truth`: virginica, versicolor, setosa - `estimate`: setosa, versicolor, virginica + x `truth` and `estimate` levels must be equivalent. + * `truth`: virginica, versicolor, and setosa. + * `estimate`: setosa, versicolor, and virginica. --- @@ -79,9 +79,9 @@ conf_mat(three_class, truth = onelevel, estimate = pred, dnn = c("", "")) Condition Error in `conf_mat()`: - ! `truth` and `estimate` levels must be equivalent. - `truth`: 1 - `estimate`: setosa, versicolor, virginica + x `truth` and `estimate` levels must be equivalent. + * `truth`: 1. + * `estimate`: setosa, versicolor, and virginica. --- diff --git a/tests/testthat/_snaps/error-handling.md b/tests/testthat/_snaps/error-handling.md index ff310eab..fe7123b8 100644 --- a/tests/testthat/_snaps/error-handling.md +++ b/tests/testthat/_snaps/error-handling.md @@ -13,7 +13,7 @@ sens(df, truth, estimate) Condition Error in `sens()`: - ! `truth` should be a factor, not a `numeric`. + ! `truth` should be a factor, not a a number. # At least 2 levels in truth @@ -47,7 +47,7 @@ sens(pathology, pathology, scan, estimator = "blah") Condition Error in `sens()`: - ! `estimator` must be one of: "binary", "macro", "micro", "macro_weighted". Not "blah". + ! `estimator` must be one of: binary, macro, micro, and macro_weighted, not blah. # Bad estimator + truth combination @@ -63,7 +63,7 @@ sens(hpc_cv, obs, pred, estimator = 1) Condition Error in `sens()`: - ! `estimator` must be a character, not a numeric. + ! `estimator` must be a single string, not the number 1. --- @@ -71,7 +71,7 @@ sens(hpc_cv, obs, pred, estimator = c("1", "2")) Condition Error in `sens()`: - ! `estimator` must be length 1, not 2. + ! `estimator` must be a single string, not a character vector. # Numeric matrix in numeric metric @@ -95,9 +95,9 @@ sens(df, x, y) Condition Error in `sens()`: - ! `truth` and `estimate` levels must be equivalent. - `truth`: a, b, c - `estimate`: a, b + x `truth` and `estimate` levels must be equivalent. + * `truth`: a, b, and c. + * `estimate`: a and b. # Multiple estimate columns for a binary metric @@ -121,7 +121,7 @@ rmse_vec(1:5, 1:6) Condition Error in `rmse_vec()`: - ! Length of `truth` (5) and `estimate` (6) must match. + ! `truth` (5) and `estimate` (6) must be the same length. # Missing arguments diff --git a/tests/testthat/_snaps/fair-aaa.md b/tests/testthat/_snaps/fair-aaa.md index a2b90fa0..ea67345f 100644 --- a/tests/testthat/_snaps/fair-aaa.md +++ b/tests/testthat/_snaps/fair-aaa.md @@ -85,7 +85,7 @@ bad_truth_metric_set(hpc_cv, truth = VF, estimate = pred) Condition Error in `bop()`: - ! `truth` should be a factor, not a `numeric`. + ! `truth` should be a factor, not a a double vector. --- @@ -93,7 +93,7 @@ bad_truth_metric(hpc_cv, truth = VF, estimate = pred) Condition Error in `bop()`: - ! `truth` should be a factor, not a `numeric`. + ! `truth` should be a factor, not a a double vector. # outputted function errors informatively with redundant grouping diff --git a/tests/testthat/_snaps/prob-classification_cost.md b/tests/testthat/_snaps/prob-classification_cost.md index ba5df219..e0228e07 100644 --- a/tests/testthat/_snaps/prob-classification_cost.md +++ b/tests/testthat/_snaps/prob-classification_cost.md @@ -52,7 +52,7 @@ classification_cost(df, obs, A, costs = costs) Condition Error in `classification_cost()`: - ! `costs$truth` must be a character or factor column, not 1 and 2. + ! `costs$truth` must be a character or factor column, not a double vector. --- @@ -60,7 +60,7 @@ classification_cost(df, obs, A, costs = costs) Condition Error in `classification_cost()`: - ! `costs$estimate` must be a character or factor column, not 1 and 2. + ! `costs$estimate` must be a character or factor column, not a double vector. --- @@ -68,7 +68,7 @@ classification_cost(df, obs, A, costs = costs) Condition Error in `classification_cost()`: - ! `costs$cost` must be a numeric column, not 1 and 2. + ! `costs$cost` must be a numeric column, not a character vector. # costs$truth and costs$estimate cannot contain duplicate pairs diff --git a/tests/testthat/_snaps/prob-gain_curve.md b/tests/testthat/_snaps/prob-gain_curve.md index 6772af2b..f0712792 100644 --- a/tests/testthat/_snaps/prob-gain_curve.md +++ b/tests/testthat/_snaps/prob-gain_curve.md @@ -4,7 +4,7 @@ gain_curve(df, truth, estimate) Condition Error in `gain_curve()`: - ! `truth` should be a factor, not a `numeric`. + ! `truth` should be a factor, not a a number. # errors with class_pred input diff --git a/tests/testthat/_snaps/prob-lift_curve.md b/tests/testthat/_snaps/prob-lift_curve.md index f03d72f5..067d2d36 100644 --- a/tests/testthat/_snaps/prob-lift_curve.md +++ b/tests/testthat/_snaps/prob-lift_curve.md @@ -4,7 +4,7 @@ lift_curve(df, truth, estimate) Condition Error in `lift_curve()`: - ! `truth` should be a factor, not a `numeric`. + ! `truth` should be a factor, not a a number. # errors with class_pred input diff --git a/tests/testthat/_snaps/template.md b/tests/testthat/_snaps/template.md index e7835f4d..0cd574bf 100644 --- a/tests/testthat/_snaps/template.md +++ b/tests/testthat/_snaps/template.md @@ -127,7 +127,7 @@ data = lung_surv, truth = .pred_time, .pred) Condition Error: - ! `truth` should be a Surv object, not a `numeric`. + ! `truth` should be a Surv object, not a a double vector. --- @@ -136,7 +136,7 @@ data = lung_surv, truth = surv_obj, surv_obj) Condition Error: - ! `estimate` should be a list, not a `Surv`. + ! `estimate` should be a list, not a a object. # static_survival_metric_summarizer()'s errors with bad input @@ -164,7 +164,7 @@ data = lung_surv, truth = surv_obj, estimate = list) Condition Error: - ! `estimate` should be a numeric, not a `list`. + ! `estimate` should be a numeric, not a list. --- @@ -184,7 +184,7 @@ data = lung_surv, truth = .pred_time, .pred) Condition Error: - ! `truth` should be a Surv object, not a `numeric`. + ! `truth` should be a Surv object, not a a double vector. --- @@ -193,5 +193,5 @@ data = lung_surv, truth = surv_obj, surv_obj) Condition Error: - ! `estimate` should be a list, not a `Surv`. + ! `estimate` should be a list, not a a object. diff --git a/tests/testthat/_snaps/validation.md b/tests/testthat/_snaps/validation.md index f0246a03..9cc0bb3a 100644 --- a/tests/testthat/_snaps/validation.md +++ b/tests/testthat/_snaps/validation.md @@ -4,7 +4,7 @@ validate_numeric_truth_numeric_estimate("1", 1) Condition Error: - ! `truth` should be a numeric, not a `character`. + ! `truth` should be a numeric, not a string. --- @@ -12,7 +12,7 @@ validate_numeric_truth_numeric_estimate(1, "1") Condition Error: - ! `estimate` should be a numeric, not a `character`. + ! `estimate` should be a numeric, not a string. --- @@ -36,7 +36,7 @@ validate_numeric_truth_numeric_estimate(1:4, 1:5) Condition Error: - ! Length of `truth` (4) and `estimate` (5) must match. + ! `truth` (4) and `estimate` (5) must be the same length. --- @@ -53,7 +53,7 @@ validate_factor_truth_factor_estimate("1", 1) Condition Error: - ! `truth` should be a factor, not a `character`. + ! `truth` should be a factor, not a a string. --- @@ -62,7 +62,7 @@ levels = c("a", "b"))) Condition Error: - ! `truth` should be a factor, not a `character`. + ! `truth` should be a factor, not a a character vector. --- @@ -71,7 +71,7 @@ "b")), c("a", "b", "a")) Condition Error: - ! `estimate` should be a factor, not a `character`. + ! `estimate` should be a factor, not a a character vector. --- @@ -80,7 +80,7 @@ "b")), 1:3) Condition Error: - ! `estimate` should be a factor, not a `integer`. + ! `estimate` should be a factor, not a an integer vector. --- @@ -89,9 +89,9 @@ "b")), factor(c("a", "a", "a"), levels = c("a", "b", "c"))) Condition Error: - ! `truth` and `estimate` levels must be equivalent. - `truth`: a, b - `estimate`: a, b, c + x `truth` and `estimate` levels must be equivalent. + * `truth`: a and b. + * `estimate`: a, b, and c. --- @@ -100,7 +100,7 @@ "b")), factor(c("a", "a", "a", "a"), levels = c("a", "b"))) Condition Error: - ! Length of `truth` (3) and `estimate` (4) must match. + ! `truth` (3) and `estimate` (4) must be the same length. # validate_factor_truth_matrix_estimate errors as expected for binary @@ -108,7 +108,7 @@ validate_factor_truth_matrix_estimate(c("a", "b", "a"), 1:3, estimator = "binary") Condition Error: - ! `truth` should be a factor, not a `character`. + ! `truth` should be a factor, not a a character vector. --- @@ -117,7 +117,7 @@ "b")), c("a", "b", "a"), estimator = "binary") Condition Error: - ! `estimate` should be a numeric vector, not a `character` vector. + ! `estimate` should be a numeric vector, not a character vector. --- @@ -144,7 +144,7 @@ estimator = "non binary") Condition Error: - ! `truth` should be a factor, not a `character`. + ! `truth` should be a factor, not a a character vector. --- @@ -162,7 +162,7 @@ "b")), matrix(as.character(1:6), ncol = 2), estimator = "non binary") Condition Error: - ! The columns supplied in `...` should be numerics, not `character`s. + ! The columns supplied in `...` should be numerics, not . --- @@ -179,7 +179,7 @@ validate_surv_truth_numeric_estimate("1", 1) Condition Error: - ! `truth` should be a Surv object, not a `character`. + ! `truth` should be a Surv object, not a string. --- @@ -188,7 +188,7 @@ .pred_time)) Condition Error: - ! `estimate` should be a numeric, not a `character`. + ! `estimate` should be a numeric, not a character vector. --- @@ -197,7 +197,7 @@ .pred_time) Condition Error: - ! Length of `truth` (5) and `estimate` (228) must match. + ! `truth` (5) and `estimate` (228) must be the same length. # validate_surv_truth_list_estimate errors as expected @@ -205,7 +205,7 @@ validate_surv_truth_list_estimate("1", 1) Condition Error: - ! `truth` should be a Surv object, not a `character`. + ! `truth` should be a Surv object, not a a string. --- @@ -221,7 +221,7 @@ validate_surv_truth_list_estimate(lung_surv$surv_obj, lung_surv$list2) Condition Error: - ! All data.frames of `estimate` should include column names: `.eval_time`, `.pred_survival`, and `.weight_censored`. + ! All data.frames of `estimate` should include column names: (.eval_time), (.pred_survival), and (.weight_censored). --- @@ -229,7 +229,7 @@ validate_surv_truth_list_estimate(lung_surv$surv_obj, lung_surv$list4) Condition Error: - ! All data.frames of `estimate` should include column names: `.eval_time`, `.pred_survival`, and `.weight_censored`. + ! All data.frames of `estimate` should include column names: (.eval_time), (.pred_survival), and (.weight_censored). --- @@ -238,7 +238,7 @@ .pred_time)) Condition Error: - ! `estimate` should be a list, not a `character`. + ! `estimate` should be a list, not a a character vector. --- @@ -247,7 +247,7 @@ .pred_time) Condition Error: - ! `estimate` should be a list, not a `numeric`. + ! `estimate` should be a list, not a a double vector. # validate_case_weights errors as expected @@ -255,5 +255,5 @@ validate_case_weights(1:10, 11) Condition Error: - ! `case_weights` (10) must have the same length as `truth` (11). + ! `truth` (11) and `case_weights` (10) must be the same length. From f2b5140cf695b65f256532276a2fa67261c27dd4 Mon Sep 17 00:00:00 2001 From: Emil Hvitfeldt Date: Wed, 15 Nov 2023 18:19:04 -0800 Subject: [PATCH 2/5] no more stop() calls --- R/aaa-metrics.R | 11 +++++------ R/conf_mat.R | 21 ++++++++++++++++----- R/misc.R | 17 +++++++++++++---- tests/testthat/_snaps/aaa-metrics.md | 4 ++-- tests/testthat/_snaps/error-handling.md | 8 ++++---- tests/testthat/_snaps/flatten.md | 4 ++-- 6 files changed, 42 insertions(+), 23 deletions(-) diff --git a/R/aaa-metrics.R b/R/aaa-metrics.R index 8785e062..6e4c8b35 100644 --- a/R/aaa-metrics.R +++ b/R/aaa-metrics.R @@ -547,18 +547,17 @@ validate_not_empty <- function(x, call = caller_env()) { } } -validate_inputs_are_functions <- function(fns) { +validate_inputs_are_functions <- function(fns, call = caller_env()) { # Check that the user supplied all functions is_fun_vec <- vapply(fns, is_function, logical(1)) all_fns <- all(is_fun_vec) if (!all_fns) { not_fn <- which(!is_fun_vec) - not_fn <- paste(not_fn, collapse = ", ") - stop( - "All inputs to `metric_set()` must be functions. ", - "These inputs are not: (", not_fn, ").", - call. = FALSE + cli::cli_abort( + "All inputs to {.fn metric_set} must be functions. \\ + These inputs are not: {not_fn}.", + call = call ) } } diff --git a/R/conf_mat.R b/R/conf_mat.R index d6ff1b3b..f8bfcce0 100644 --- a/R/conf_mat.R +++ b/R/conf_mat.R @@ -292,13 +292,24 @@ tidy.conf_mat <- function(x, ...) { ) } -flatten <- function(xtab) { - p <- ncol(xtab) - if (nrow(xtab) != p) { - stop("table must have equal dimensions") +flatten <- function(xtab, call = caller_env()) { + n_col <- ncol(xtab) + n_row <- nrow(xtab) + if (n_row != n_col) { + cli::cli_abort( + "{.arg x} must have equal dimensions. \\ + {.arg x} has {n_col} columns and {n_row} rows.", + call = call + ) } flat <- as.vector(xtab) - names(flat) <- paste("cell", rep(1:p, p), rep(1:p, each = p), sep = "_") + names(flat) <- paste( + "cell", + rep(seq_len(n_col), n_col), + rep(seq_len(n_col), each = n_col), + sep = "_" + ) + flat } diff --git a/R/misc.R b/R/misc.R index 13f74b3b..d4360fc4 100644 --- a/R/misc.R +++ b/R/misc.R @@ -28,12 +28,21 @@ neg_val <- function(xtab, event_level) { # ------------------------------------------------------------------------------ -check_table <- function(x) { - if (!identical(nrow(x), ncol(x))) { - stop("the table must have nrow = ncol", call. = FALSE) +check_table <- function(x, call = caller_env()) { + n_col <- ncol(x) + n_row <- nrow(x) + if (n_row != n_col) { + cli::cli_abort( + "{.arg x} must have equal dimensions. \\ + {.arg x} has {n_col} columns and {n_row} rows.", + call = call + ) } if (!isTRUE(all.equal(rownames(x), colnames(x)))) { - stop("the table must the same groups in the same order", call. = FALSE) + cli::cli_abort( + "The table must the same groups in the same order.", + call = call + ) } invisible(NULL) } diff --git a/tests/testthat/_snaps/aaa-metrics.md b/tests/testthat/_snaps/aaa-metrics.md index 6d54421f..5d03cb83 100644 --- a/tests/testthat/_snaps/aaa-metrics.md +++ b/tests/testthat/_snaps/aaa-metrics.md @@ -40,8 +40,8 @@ Code metric_set(rmse, "x") Condition - Error: - ! All inputs to `metric_set()` must be functions. These inputs are not: (2). + Error in `metric_set()`: + ! All inputs to `metric_set()` must be functions. These inputs are not: 2. # mixing bad metric sets diff --git a/tests/testthat/_snaps/error-handling.md b/tests/testthat/_snaps/error-handling.md index fe7123b8..188bd33c 100644 --- a/tests/testthat/_snaps/error-handling.md +++ b/tests/testthat/_snaps/error-handling.md @@ -144,14 +144,14 @@ Code sens(as.table(matrix(1:6, 2))) Condition - Error: - ! the table must have nrow = ncol + Error in `sens()`: + ! `x` must have equal dimensions. `x` has 3 columns and 2 rows. --- Code sens(as.table(matrix(1:4, 2, dimnames = list(c("A", "B"), c("A", "C"))))) Condition - Error: - ! the table must the same groups in the same order + Error in `sens()`: + ! The table must the same groups in the same order. diff --git a/tests/testthat/_snaps/flatten.md b/tests/testthat/_snaps/flatten.md index 2ea349cf..ba964ceb 100644 --- a/tests/testthat/_snaps/flatten.md +++ b/tests/testthat/_snaps/flatten.md @@ -3,6 +3,6 @@ Code yardstick:::flatten(three_class_tb[, 1:2]) Condition - Error in `yardstick:::flatten()`: - ! table must have equal dimensions + Error: + ! `x` must have equal dimensions. `x` has 2 columns and 3 rows. From c6a0440ebfe396869f83f3d1c0cd0310624faf1d Mon Sep 17 00:00:00 2001 From: Emil Hvitfeldt Date: Wed, 15 Nov 2023 20:05:12 -0800 Subject: [PATCH 3/5] move away from warn() --- R/class-precision.R | 39 +++++++++++-------- R/class-recall.R | 39 +++++++++++-------- R/class-sens.R | 39 +++++++++++-------- R/class-spec.R | 39 +++++++++++-------- R/misc.R | 2 +- R/prob-binary-thresholds.R | 4 +- R/prob-roc_auc.R | 29 +++++--------- tests/testthat/_snaps/class-f_meas.md | 28 ++++++------- tests/testthat/_snaps/class-j_index.md | 17 ++++---- tests/testthat/_snaps/class-ppv.md | 4 +- tests/testthat/_snaps/class-precision.md | 12 +++--- tests/testthat/_snaps/class-recall.md | 9 ++--- tests/testthat/_snaps/class-sens.md | 9 ++--- tests/testthat/_snaps/class-spec.md | 6 +-- .../testthat/_snaps/prob-average_precision.md | 6 +-- tests/testthat/_snaps/prob-pr_curve.md | 2 +- tests/testthat/_snaps/prob-roc_auc.md | 17 ++++++-- tests/testthat/test-prob-roc_auc.R | 5 +-- 18 files changed, 160 insertions(+), 146 deletions(-) diff --git a/R/class-precision.R b/R/class-precision.R index b6a2eaa6..4260ab0b 100644 --- a/R/class-precision.R +++ b/R/class-precision.R @@ -178,14 +178,20 @@ precision_multiclass <- function(data, estimator) { } warn_precision_undefined_binary <- function(event, count) { - message <- paste0( - "While computing binary `precision()`, no predicted events were detected ", - "(i.e. `true_positive + false_positive = 0`). ", - "\n", - "Precision is undefined in this case, and `NA` will be returned.", - "\n", - "Note that ", count, " true event(s) actually occured for the problematic ", - "event level, '", event, "'." + message <- c( + "While computing binary {.fn precision}, no predicted events were \\ + detected (i.e. `true_positive + false_positive = 0`).", + "Precision is undefined in this case, and `NA` will be returned." + ) + + message <- c( + message, + paste( + "Note that", + count, + "true event(s) actually occured for the problematic event level,", + event + ) ) warn_precision_undefined( @@ -197,14 +203,13 @@ warn_precision_undefined_binary <- function(event, count) { } warn_precision_undefined_multiclass <- function(events, counts) { - message <- paste0( - "While computing multiclass `precision()`, some levels had no predicted events ", - "(i.e. `true_positive + false_positive = 0`). ", - "\n", - "Precision is undefined in this case, and those levels will be removed from the averaged result.", - "\n", - "Note that the following number of true events actually occured for each problematic event level:", - "\n", + message <- c( + "While computing multiclass {.fn precision}, some levels had no predicted \\ + events (i.e. `true_positive + false_positive = 0`).", + "Precision is undefined in this case, and those levels will be removed \\ + from the averaged result.", + "Note that the following number of true events actually occured for each \\ + problematic event level:", paste0("'", events, "': ", counts, collapse = "\n") ) @@ -217,7 +222,7 @@ warn_precision_undefined_multiclass <- function(events, counts) { } warn_precision_undefined <- function(message, events, counts, ..., class = character()) { - warn( + cli::cli_warn( message = message, class = c(class, "yardstick_warning_precision_undefined"), events = events, diff --git a/R/class-recall.R b/R/class-recall.R index 52a4ea1c..65e80104 100644 --- a/R/class-recall.R +++ b/R/class-recall.R @@ -179,14 +179,20 @@ recall_multiclass <- function(data, estimator) { warn_recall_undefined_binary <- function(event, count) { - message <- paste0( - "While computing binary `recall()`, no true events were detected ", - "(i.e. `true_positive + false_negative = 0`). ", - "\n", - "Recall is undefined in this case, and `NA` will be returned.", - "\n", - "Note that ", count, " predicted event(s) actually occured for the problematic ", - "event level, '", event, "'." + message <- c( + "While computing binary {.fn recall}, no true events were detected \\ + (i.e. `true_positive + false_negative = 0`).", + "Recall is undefined in this case, and `NA` will be returned." + ) + + message <- c( + message, + paste( + "Note that", + count, + "predicted event(s) actually occured for the problematic event level", + event + ) ) warn_recall_undefined( @@ -198,14 +204,13 @@ warn_recall_undefined_binary <- function(event, count) { } warn_recall_undefined_multiclass <- function(events, counts) { - message <- paste0( - "While computing multiclass `recall()`, some levels had no true events ", - "(i.e. `true_positive + false_negative = 0`). ", - "\n", - "Recall is undefined in this case, and those levels will be removed from the averaged result.", - "\n", - "Note that the following number of predicted events actually occured for each problematic event level:", - "\n", + message <- c( + "While computing multiclass {.fn recall}, some levels had no true events \\ + (i.e. `true_positive + false_negative = 0`).", + "Recall is undefined in this case, and those levels will be removed from \\ + the averaged result.", + "Note that the following number of predicted events actually occured for \\ + each problematic event level:", paste0("'", events, "': ", counts, collapse = "\n") ) @@ -218,7 +223,7 @@ warn_recall_undefined_multiclass <- function(events, counts) { } warn_recall_undefined <- function(message, events, counts, ..., class = character()) { - warn( + cli::cli_warn( message = message, class = c(class, "yardstick_warning_recall_undefined"), events = events, diff --git a/R/class-sens.R b/R/class-sens.R index 4eb7a5c0..89684e4e 100644 --- a/R/class-sens.R +++ b/R/class-sens.R @@ -277,14 +277,20 @@ sens_multiclass <- function(data, estimator) { warn_sens_undefined_binary <- function(event, count) { - message <- paste0( - "While computing binary `sens()`, no true events were detected ", - "(i.e. `true_positive + false_negative = 0`). ", - "\n", - "Sensitivity is undefined in this case, and `NA` will be returned.", - "\n", - "Note that ", count, " predicted event(s) actually occured for the problematic ", - "event level, '", event, "'." + message <- c( + "While computing binary {.fn sens}, no true events were detected \\ + (i.e. `true_positive + false_negative = 0`).", + "Sensitivity is undefined in this case, and `NA` will be returned." + ) + + message <- c( + message, + paste( + "Note that", + count, + "predicted event(s) actually occured for the problematic event level,", + event + ) ) warn_sens_undefined( @@ -296,14 +302,13 @@ warn_sens_undefined_binary <- function(event, count) { } warn_sens_undefined_multiclass <- function(events, counts) { - message <- paste0( - "While computing multiclass `sens()`, some levels had no true events ", - "(i.e. `true_positive + false_negative = 0`). ", - "\n", - "Sensitivity is undefined in this case, and those levels will be removed from the averaged result.", - "\n", - "Note that the following number of predicted events actually occured for each problematic event level:", - "\n", + message <- c( + "While computing multiclass {.fn sens}, some levels had no true events \\ + (i.e. `true_positive + false_negative = 0`).", + "Sensitivity is undefined in this case, and those levels will be removed \\ + from the averaged result.", + "Note that the following number of predicted events actually occured for \\ + each problematic event level:", paste0("'", events, "': ", counts, collapse = "\n") ) @@ -316,7 +321,7 @@ warn_sens_undefined_multiclass <- function(events, counts) { } warn_sens_undefined <- function(message, events, counts, ..., class = character()) { - warn( + cli::cli_warn( message = message, class = c(class, "yardstick_warning_sens_undefined"), events = events, diff --git a/R/class-spec.R b/R/class-spec.R index 21d00b39..cc1002ea 100644 --- a/R/class-spec.R +++ b/R/class-spec.R @@ -247,14 +247,20 @@ spec_multiclass <- function(data, estimator) { warn_spec_undefined_binary <- function(event, count) { - message <- paste0( - "While computing binary `spec()`, no true negatives were detected ", - "(i.e. `true_negative + false_positive = 0`). ", - "\n", - "Specificity is undefined in this case, and `NA` will be returned.", - "\n", - "Note that ", count, " predicted negatives(s) actually occured for the problematic ", - "event level, '", event, "'." + message <- c( + "While computing binary {.fn spec}, no true negatives were detected \\ + (i.e. `true_negative + false_positive = 0`).", + "Specificity is undefined in this case, and `NA` will be returned." + ) + + message <- c( + message, + paste( + "Note that", + count, + "predicted negatives(s) actually occured for the problematic event level,", + event + ) ) warn_spec_undefined( @@ -266,14 +272,13 @@ warn_spec_undefined_binary <- function(event, count) { } warn_spec_undefined_multiclass <- function(events, counts) { - message <- paste0( - "While computing multiclass `spec()`, some levels had no true negatives ", - "(i.e. `true_negative + false_positive = 0`). ", - "\n", - "Specificity is undefined in this case, and those levels will be removed from the averaged result.", - "\n", - "Note that the following number of predicted negatives actually occured for each problematic event level:", - "\n", + message <- c( + "While computing multiclass {.fn spec}, some levels had no true negatives \\ + (i.e. `true_negative + false_positive = 0`).", + "Specificity is undefined in this case, and those levels will be removed \\ + from the averaged result.", + "Note that the following number of predicted negatives actually occured \\ + for each problematic event level:", paste0("'", events, "': ", counts, collapse = "\n") ) @@ -286,7 +291,7 @@ warn_spec_undefined_multiclass <- function(events, counts) { } warn_spec_undefined <- function(message, events, counts, ..., class = character()) { - warn( + cli::cli_warn( message = message, class = c(class, "yardstick_warning_spec_undefined"), events = events, diff --git a/R/misc.R b/R/misc.R index d4360fc4..af5ccff2 100644 --- a/R/misc.R +++ b/R/misc.R @@ -335,7 +335,7 @@ make_correlation_undefined_constant_message <- function(what) { } warn_correlation_undefined <- function(message, ..., class = character()) { - warn( + cli::cli_warn( message = message, class = c(class, "yardstick_warning_correlation_undefined"), ... diff --git a/R/prob-binary-thresholds.R b/R/prob-binary-thresholds.R index e718722b..4d82aa46 100644 --- a/R/prob-binary-thresholds.R +++ b/R/prob-binary-thresholds.R @@ -84,7 +84,9 @@ binary_threshold_curve <- function(truth, case_weights_non_events <- (1 - truth) * case_weights if (sum(case_weights_events) == 0L) { - warn("There are `0` event cases in `truth`, results will be meaningless.") + cli::cli_warn( + "There are 0 event cases in {.arg truth}, results will be meaningless." + ) } tp <- cumsum(case_weights_events) diff --git a/R/prob-roc_auc.R b/R/prob-roc_auc.R index 728dd64d..da96de29 100644 --- a/R/prob-roc_auc.R +++ b/R/prob-roc_auc.R @@ -313,17 +313,12 @@ roc_auc_hand_till <- function(truth, estimate) { indicator_missing <- is.na(lvls_loc) lvls_missing <- lvls[indicator_missing] - lvls_missing <- single_quote(lvls_missing) - lvls_missing <- paste0(lvls_missing, collapse = ", ") - msg <- paste0( - "No observations were detected in `truth` for level(s): ", - lvls_missing, - "\n", - "Computation will proceed by ignoring those levels." - ) - - warn(msg) + cli::cli_warn(c( + x = "No observations were detected in {.arg truth} for level{?s}: \\ + {lvls_missing}.", + i = "Computation will proceed by ignoring those levels." + )) # Proceed with non-missing levels lvls <- lvls[!indicator_missing] @@ -391,12 +386,12 @@ compute_n_occurrences <- function(x, what) { msg_roc_truth_no_control <- function(control) { paste0( - "No control observations were detected in `truth` ", + "No control observations were detected in {.arg truth} ", "with control level '", control, "'." ) } warn_roc_truth_no_control <- function(control) { - warn( + cli::cli_warn( msg_roc_truth_no_control(control), class = "yardstick_warning_roc_truth_no_control" ) @@ -410,12 +405,12 @@ stop_roc_truth_no_control <- function(control) { msg_roc_truth_no_event <- function(event) { paste0( - "No event observations were detected in `truth` ", + "No event observations were detected in {.arg truth} ", "with event level '", event, "'." ) } warn_roc_truth_no_event <- function(event) { - warn( + cli::cli_warn( msg_roc_truth_no_event(event), class = "yardstick_warning_roc_truth_no_event" ) @@ -426,9 +421,3 @@ stop_roc_truth_no_event <- function(event) { class = "yardstick_error_roc_truth_no_event" ) } - -# ------------------------------------------------------------------------------ - -single_quote <- function(x) { - encodeString(x, quote = "'", na.encode = FALSE) -} diff --git a/tests/testthat/_snaps/class-f_meas.md b/tests/testthat/_snaps/class-f_meas.md index ae33112d..049551ad 100644 --- a/tests/testthat/_snaps/class-f_meas.md +++ b/tests/testthat/_snaps/class-f_meas.md @@ -4,16 +4,16 @@ out <- precision_vec(truth, estimate) Condition Warning: - While computing binary `precision()`, no predicted events were detected (i.e. `true_positive + false_positive = 0`). + While computing binary `precision()`, no predicted events were detected (i.e. `true_positive + false_positive = 0`). Precision is undefined in this case, and `NA` will be returned. - Note that 2 true event(s) actually occured for the problematic event level, 'a'. + Note that 2 true event(s) actually occured for the problematic event level, a Code expect <- f_meas_vec(truth, estimate) Condition Warning: - While computing binary `precision()`, no predicted events were detected (i.e. `true_positive + false_positive = 0`). + While computing binary `precision()`, no predicted events were detected (i.e. `true_positive + false_positive = 0`). Precision is undefined in this case, and `NA` will be returned. - Note that 2 true event(s) actually occured for the problematic event level, 'a'. + Note that 2 true event(s) actually occured for the problematic event level, a # `NA` values propagate from binary `recall()` @@ -21,16 +21,16 @@ out <- recall_vec(truth, estimate) Condition Warning: - While computing binary `recall()`, no true events were detected (i.e. `true_positive + false_negative = 0`). + While computing binary `recall()`, no true events were detected (i.e. `true_positive + false_negative = 0`). Recall is undefined in this case, and `NA` will be returned. - Note that 2 predicted event(s) actually occured for the problematic event level, 'a'. + Note that 2 predicted event(s) actually occured for the problematic event level a Code expect <- f_meas_vec(truth, estimate) Condition Warning: - While computing binary `recall()`, no true events were detected (i.e. `true_positive + false_negative = 0`). + While computing binary `recall()`, no true events were detected (i.e. `true_positive + false_negative = 0`). Recall is undefined in this case, and `NA` will be returned. - Note that 2 predicted event(s) actually occured for the problematic event level, 'a'. + Note that 2 predicted event(s) actually occured for the problematic event level a # Binary `f_meas()` returns `NA` with a warning when recall is undefined (tp + fn = 0) (#98) @@ -38,9 +38,9 @@ out <- f_meas_vec(truth, estimate) Condition Warning: - While computing binary `recall()`, no true events were detected (i.e. `true_positive + false_negative = 0`). + While computing binary `recall()`, no true events were detected (i.e. `true_positive + false_negative = 0`). Recall is undefined in this case, and `NA` will be returned. - Note that 1 predicted event(s) actually occured for the problematic event level, 'a'. + Note that 1 predicted event(s) actually occured for the problematic event level a # Binary `f_meas()` returns `NA` with a warning when precision is undefined (tp + fp = 0) (#98) @@ -48,9 +48,9 @@ out <- f_meas_vec(truth, estimate) Condition Warning: - While computing binary `precision()`, no predicted events were detected (i.e. `true_positive + false_positive = 0`). + While computing binary `precision()`, no predicted events were detected (i.e. `true_positive + false_positive = 0`). Precision is undefined in this case, and `NA` will be returned. - Note that 1 true event(s) actually occured for the problematic event level, 'a'. + Note that 1 true event(s) actually occured for the problematic event level, a # Multiclass `f_meas()` returns averaged value with `NA`s removed + a warning when recall is undefined (tp + fn = 0) (#98) @@ -58,7 +58,7 @@ out <- f_meas_vec(truth, estimate) Condition Warning: - While computing multiclass `recall()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). + While computing multiclass `recall()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). Recall is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted events actually occured for each problematic event level: 'c': 1 @@ -69,7 +69,7 @@ out <- f_meas_vec(truth, estimate) Condition Warning: - While computing multiclass `precision()`, some levels had no predicted events (i.e. `true_positive + false_positive = 0`). + While computing multiclass `precision()`, some levels had no predicted events (i.e. `true_positive + false_positive = 0`). Precision is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of true events actually occured for each problematic event level: 'c': 1 diff --git a/tests/testthat/_snaps/class-j_index.md b/tests/testthat/_snaps/class-j_index.md index aa868a93..e7071877 100644 --- a/tests/testthat/_snaps/class-j_index.md +++ b/tests/testthat/_snaps/class-j_index.md @@ -4,9 +4,9 @@ out <- j_index_vec(truth, estimate) Condition Warning: - While computing binary `sens()`, no true events were detected (i.e. `true_positive + false_negative = 0`). + While computing binary `sens()`, no true events were detected (i.e. `true_positive + false_negative = 0`). Sensitivity is undefined in this case, and `NA` will be returned. - Note that 1 predicted event(s) actually occured for the problematic event level, 'a'. + Note that 1 predicted event(s) actually occured for the problematic event level, a # Binary `j_index()` returns `NA` with a warning when specificity is undefined (tn + fp = 0) (#265) @@ -14,9 +14,9 @@ out <- j_index_vec(truth, estimate) Condition Warning: - While computing binary `spec()`, no true negatives were detected (i.e. `true_negative + false_positive = 0`). + While computing binary `spec()`, no true negatives were detected (i.e. `true_negative + false_positive = 0`). Specificity is undefined in this case, and `NA` will be returned. - Note that 1 predicted negatives(s) actually occured for the problematic event level, 'a'. + Note that 1 predicted negatives(s) actually occured for the problematic event level, a # Multiclass `j_index()` returns averaged value with `NA`s removed + a warning when sensitivity is undefined (tp + fn = 0) (#265) @@ -24,7 +24,7 @@ out <- j_index_vec(truth, estimate) Condition Warning: - While computing multiclass `sens()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). + While computing multiclass `sens()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). Sensitivity is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted events actually occured for each problematic event level: 'c': 1 @@ -35,13 +35,12 @@ out <- j_index_vec(truth, estimate) Condition Warning: - While computing multiclass `sens()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). + While computing multiclass `sens()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). Sensitivity is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted events actually occured for each problematic event level: - 'b': 1 - 'c': 1 + 'b': 1 'c': 1 Warning: - While computing multiclass `spec()`, some levels had no true negatives (i.e. `true_negative + false_positive = 0`). + While computing multiclass `spec()`, some levels had no true negatives (i.e. `true_negative + false_positive = 0`). Specificity is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted negatives actually occured for each problematic event level: 'a': 2 diff --git a/tests/testthat/_snaps/class-ppv.md b/tests/testthat/_snaps/class-ppv.md index c0332ae5..a40fa0cf 100644 --- a/tests/testthat/_snaps/class-ppv.md +++ b/tests/testthat/_snaps/class-ppv.md @@ -4,9 +4,9 @@ out <- ppv_vec(truth, estimate) Condition Warning: - While computing binary `sens()`, no true events were detected (i.e. `true_positive + false_negative = 0`). + While computing binary `sens()`, no true events were detected (i.e. `true_positive + false_negative = 0`). Sensitivity is undefined in this case, and `NA` will be returned. - Note that 1 predicted event(s) actually occured for the problematic event level, 'a'. + Note that 1 predicted event(s) actually occured for the problematic event level, a # work with class_pred input diff --git a/tests/testthat/_snaps/class-precision.md b/tests/testthat/_snaps/class-precision.md index 4fa54bda..df7c1e47 100644 --- a/tests/testthat/_snaps/class-precision.md +++ b/tests/testthat/_snaps/class-precision.md @@ -4,9 +4,9 @@ out <- precision_vec(truth, estimate) Condition Warning: - While computing binary `precision()`, no predicted events were detected (i.e. `true_positive + false_positive = 0`). + While computing binary `precision()`, no predicted events were detected (i.e. `true_positive + false_positive = 0`). Precision is undefined in this case, and `NA` will be returned. - Note that 1 true event(s) actually occured for the problematic event level, 'a'. + Note that 1 true event(s) actually occured for the problematic event level, a # Multiclass `precision()` returns averaged value with `NA`s removed + a warning when undefined (tp + fp = 0) (#98) @@ -14,12 +14,10 @@ out <- precision_vec(truth, estimate) Condition Warning: - While computing multiclass `precision()`, some levels had no predicted events (i.e. `true_positive + false_positive = 0`). + While computing multiclass `precision()`, some levels had no predicted events (i.e. `true_positive + false_positive = 0`). Precision is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of true events actually occured for each problematic event level: - 'a': 1 - 'b': 1 - 'c': 1 + 'a': 1 'b': 1 'c': 1 --- @@ -27,7 +25,7 @@ out <- precision_vec(truth, estimate) Condition Warning: - While computing multiclass `precision()`, some levels had no predicted events (i.e. `true_positive + false_positive = 0`). + While computing multiclass `precision()`, some levels had no predicted events (i.e. `true_positive + false_positive = 0`). Precision is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of true events actually occured for each problematic event level: 'c': 1 diff --git a/tests/testthat/_snaps/class-recall.md b/tests/testthat/_snaps/class-recall.md index 6267250c..8a6f13a6 100644 --- a/tests/testthat/_snaps/class-recall.md +++ b/tests/testthat/_snaps/class-recall.md @@ -4,9 +4,9 @@ out <- recall_vec(truth, estimate) Condition Warning: - While computing binary `recall()`, no true events were detected (i.e. `true_positive + false_negative = 0`). + While computing binary `recall()`, no true events were detected (i.e. `true_positive + false_negative = 0`). Recall is undefined in this case, and `NA` will be returned. - Note that 1 predicted event(s) actually occured for the problematic event level, 'a'. + Note that 1 predicted event(s) actually occured for the problematic event level a # Multiclass `recall()` returns averaged value with `NA`s removed + a warning when undefined (tp + fn = 0) (#98) @@ -14,11 +14,10 @@ out <- recall_vec(truth, estimate) Condition Warning: - While computing multiclass `recall()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). + While computing multiclass `recall()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). Recall is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted events actually occured for each problematic event level: - 'b': 0 - 'c': 1 + 'b': 0 'c': 1 # work with class_pred input diff --git a/tests/testthat/_snaps/class-sens.md b/tests/testthat/_snaps/class-sens.md index 71ea7667..cfea7530 100644 --- a/tests/testthat/_snaps/class-sens.md +++ b/tests/testthat/_snaps/class-sens.md @@ -4,9 +4,9 @@ out <- sens_vec(truth, estimate) Condition Warning: - While computing binary `sens()`, no true events were detected (i.e. `true_positive + false_negative = 0`). + While computing binary `sens()`, no true events were detected (i.e. `true_positive + false_negative = 0`). Sensitivity is undefined in this case, and `NA` will be returned. - Note that 1 predicted event(s) actually occured for the problematic event level, 'a'. + Note that 1 predicted event(s) actually occured for the problematic event level, a # Multiclass `sens()` returns averaged value with `NA`s removed + a warning when undefined (tp + fn = 0) (#98) @@ -14,11 +14,10 @@ out <- sens_vec(truth, estimate) Condition Warning: - While computing multiclass `sens()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). + While computing multiclass `sens()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). Sensitivity is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted events actually occured for each problematic event level: - 'b': 0 - 'c': 1 + 'b': 0 'c': 1 # work with class_pred input diff --git a/tests/testthat/_snaps/class-spec.md b/tests/testthat/_snaps/class-spec.md index cd67e613..f06d8c0d 100644 --- a/tests/testthat/_snaps/class-spec.md +++ b/tests/testthat/_snaps/class-spec.md @@ -4,9 +4,9 @@ out <- spec_vec(truth, estimate) Condition Warning: - While computing binary `spec()`, no true negatives were detected (i.e. `true_negative + false_positive = 0`). + While computing binary `spec()`, no true negatives were detected (i.e. `true_negative + false_positive = 0`). Specificity is undefined in this case, and `NA` will be returned. - Note that 1 predicted negatives(s) actually occured for the problematic event level, 'a'. + Note that 1 predicted negatives(s) actually occured for the problematic event level, a # Multiclass `spec()` returns averaged value with `NA`s removed + a warning when undefined (tn + fp = 0) (#98) @@ -14,7 +14,7 @@ out <- spec_vec(truth, estimate) Condition Warning: - While computing multiclass `spec()`, some levels had no true negatives (i.e. `true_negative + false_positive = 0`). + While computing multiclass `spec()`, some levels had no true negatives (i.e. `true_negative + false_positive = 0`). Specificity is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted negatives actually occured for each problematic event level: 'a': 2 diff --git a/tests/testthat/_snaps/prob-average_precision.md b/tests/testthat/_snaps/prob-average_precision.md index cabc858b..ec4b14f0 100644 --- a/tests/testthat/_snaps/prob-average_precision.md +++ b/tests/testthat/_snaps/prob-average_precision.md @@ -4,7 +4,7 @@ out <- average_precision(df, truth, estimate)$.estimate Condition Warning: - There are `0` event cases in `truth`, results will be meaningless. + There are 0 event cases in `truth`, results will be meaningless. --- @@ -12,7 +12,7 @@ out <- average_precision(df, truth, estimate)$.estimate Condition Warning: - There are `0` event cases in `truth`, results will be meaningless. + There are 0 event cases in `truth`, results will be meaningless. --- @@ -20,7 +20,7 @@ expect <- pr_auc(df, truth, estimate)$.estimate Condition Warning: - There are `0` event cases in `truth`, results will be meaningless. + There are 0 event cases in `truth`, results will be meaningless. # errors with class_pred input diff --git a/tests/testthat/_snaps/prob-pr_curve.md b/tests/testthat/_snaps/prob-pr_curve.md index 0338948f..690f9756 100644 --- a/tests/testthat/_snaps/prob-pr_curve.md +++ b/tests/testthat/_snaps/prob-pr_curve.md @@ -4,7 +4,7 @@ out <- pr_curve(df, y, x) Condition Warning: - There are `0` event cases in `truth`, results will be meaningless. + There are 0 event cases in `truth`, results will be meaningless. # errors with class_pred input diff --git a/tests/testthat/_snaps/prob-roc_auc.md b/tests/testthat/_snaps/prob-roc_auc.md index d291c698..28e71c51 100644 --- a/tests/testthat/_snaps/prob-roc_auc.md +++ b/tests/testthat/_snaps/prob-roc_auc.md @@ -1,3 +1,12 @@ +# `roc_auc()` hand-till method ignores levels with 0 observations with a warning (#123) + + Code + expect_identical(roc_auc_vec(truth, estimate), 0.5) + Condition + Warning: + x No observations were detected in `truth` for level: y. + i Computation will proceed by ignoring those levels. + # warning is thrown when missing events Code @@ -64,8 +73,8 @@ out <- roc_auc_vec(x, estimate, estimator = "hand_till") Condition Warning: - No observations were detected in `truth` for level(s): 'y' - Computation will proceed by ignoring those levels. + x No observations were detected in `truth` for level: y. + i Computation will proceed by ignoring those levels. --- @@ -73,8 +82,8 @@ out <- roc_auc_vec(x, estimate, estimator = "hand_till") Condition Warning: - No observations were detected in `truth` for level(s): 'y', 'z' - Computation will proceed by ignoring those levels. + x No observations were detected in `truth` for levels: y and z. + i Computation will proceed by ignoring those levels. # can't use case weights and hand-till method diff --git a/tests/testthat/test-prob-roc_auc.R b/tests/testthat/test-prob-roc_auc.R index 8bee7962..d9840514 100644 --- a/tests/testthat/test-prob-roc_auc.R +++ b/tests/testthat/test-prob-roc_auc.R @@ -78,9 +78,8 @@ test_that("`roc_auc()` hand-till method ignores levels with 0 observations with colnames(estimate) <- c("x", "y", "z") # HandTill2001::auc(HandTill2001::multcap(truth, estimate)) - expect_warning( - expect_identical(roc_auc_vec(truth, estimate), 0.5), - "No observations were detected in `truth` for level[(]s[)]: 'y'" + expect_snapshot( + expect_identical(roc_auc_vec(truth, estimate), 0.5) ) }) From 7fb5e73d55b6cd6b885a8e8409f2a2b193c5b7f1 Mon Sep 17 00:00:00 2001 From: Emil Hvitfeldt Date: Wed, 15 Nov 2023 20:08:25 -0800 Subject: [PATCH 4/5] add news bullet --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 6d02b067..4d5260ef 100644 --- a/NEWS.md +++ b/NEWS.md @@ -16,6 +16,8 @@ calculated with `roc_auc_survival()`. * `demographic_parity()`, `equalized_odds()`, and `equal_opportunity()` are new metrics for measuring model fairness. Each is implemented with the `new_groupwise_metric()` constructor, a general interface for defining group-aware metrics that allows for quickly and flexibly defining fairness metrics with the problem context in mind. +* All warnings and errors have been updated to use the cli package for increased clarity and consistency. (#456, #457, #458) + # yardstick 1.2.0 ## New Metrics From 4e071b14cd94dcb9e4b28c26d55c5916cc35fdd1 Mon Sep 17 00:00:00 2001 From: Emil Hvitfeldt Date: Sun, 19 Nov 2023 12:03:24 -0800 Subject: [PATCH 5/5] one last tweak --- R/class-precision.R | 2 +- R/class-recall.R | 2 +- R/class-sens.R | 2 +- R/class-spec.R | 2 +- tests/testthat/_snaps/class-j_index.md | 2 +- tests/testthat/_snaps/class-precision.md | 2 +- tests/testthat/_snaps/class-recall.md | 2 +- tests/testthat/_snaps/class-sens.md | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/R/class-precision.R b/R/class-precision.R index 4260ab0b..5397fc53 100644 --- a/R/class-precision.R +++ b/R/class-precision.R @@ -210,7 +210,7 @@ warn_precision_undefined_multiclass <- function(events, counts) { from the averaged result.", "Note that the following number of true events actually occured for each \\ problematic event level:", - paste0("'", events, "': ", counts, collapse = "\n") + paste0("'", events, "': ", counts, collapse = ", ") ) warn_precision_undefined( diff --git a/R/class-recall.R b/R/class-recall.R index 65e80104..c7e585f7 100644 --- a/R/class-recall.R +++ b/R/class-recall.R @@ -211,7 +211,7 @@ warn_recall_undefined_multiclass <- function(events, counts) { the averaged result.", "Note that the following number of predicted events actually occured for \\ each problematic event level:", - paste0("'", events, "': ", counts, collapse = "\n") + paste0("'", events, "': ", counts, collapse = ", ") ) warn_recall_undefined( diff --git a/R/class-sens.R b/R/class-sens.R index 89684e4e..968d5596 100644 --- a/R/class-sens.R +++ b/R/class-sens.R @@ -309,7 +309,7 @@ warn_sens_undefined_multiclass <- function(events, counts) { from the averaged result.", "Note that the following number of predicted events actually occured for \\ each problematic event level:", - paste0("'", events, "': ", counts, collapse = "\n") + paste0("'", events, "': ", counts, collapse = ", ") ) warn_sens_undefined( diff --git a/R/class-spec.R b/R/class-spec.R index cc1002ea..db6e03c6 100644 --- a/R/class-spec.R +++ b/R/class-spec.R @@ -279,7 +279,7 @@ warn_spec_undefined_multiclass <- function(events, counts) { from the averaged result.", "Note that the following number of predicted negatives actually occured \\ for each problematic event level:", - paste0("'", events, "': ", counts, collapse = "\n") + paste0("'", events, "': ", counts, collapse = ", ") ) warn_spec_undefined( diff --git a/tests/testthat/_snaps/class-j_index.md b/tests/testthat/_snaps/class-j_index.md index e7071877..ec6bb7d6 100644 --- a/tests/testthat/_snaps/class-j_index.md +++ b/tests/testthat/_snaps/class-j_index.md @@ -38,7 +38,7 @@ While computing multiclass `sens()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). Sensitivity is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted events actually occured for each problematic event level: - 'b': 1 'c': 1 + 'b': 1, 'c': 1 Warning: While computing multiclass `spec()`, some levels had no true negatives (i.e. `true_negative + false_positive = 0`). Specificity is undefined in this case, and those levels will be removed from the averaged result. diff --git a/tests/testthat/_snaps/class-precision.md b/tests/testthat/_snaps/class-precision.md index df7c1e47..e64674d8 100644 --- a/tests/testthat/_snaps/class-precision.md +++ b/tests/testthat/_snaps/class-precision.md @@ -17,7 +17,7 @@ While computing multiclass `precision()`, some levels had no predicted events (i.e. `true_positive + false_positive = 0`). Precision is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of true events actually occured for each problematic event level: - 'a': 1 'b': 1 'c': 1 + 'a': 1, 'b': 1, 'c': 1 --- diff --git a/tests/testthat/_snaps/class-recall.md b/tests/testthat/_snaps/class-recall.md index 8a6f13a6..69c2e583 100644 --- a/tests/testthat/_snaps/class-recall.md +++ b/tests/testthat/_snaps/class-recall.md @@ -17,7 +17,7 @@ While computing multiclass `recall()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). Recall is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted events actually occured for each problematic event level: - 'b': 0 'c': 1 + 'b': 0, 'c': 1 # work with class_pred input diff --git a/tests/testthat/_snaps/class-sens.md b/tests/testthat/_snaps/class-sens.md index cfea7530..f4403f91 100644 --- a/tests/testthat/_snaps/class-sens.md +++ b/tests/testthat/_snaps/class-sens.md @@ -17,7 +17,7 @@ While computing multiclass `sens()`, some levels had no true events (i.e. `true_positive + false_negative = 0`). Sensitivity is undefined in this case, and those levels will be removed from the averaged result. Note that the following number of predicted events actually occured for each problematic event level: - 'b': 0 'c': 1 + 'b': 0, 'c': 1 # work with class_pred input