From 72db2b25627eb97978ef71faf0c80dbe920ca365 Mon Sep 17 00:00:00 2001 From: Matthijs Berends Date: Fri, 13 Jun 2025 14:03:21 +0200 Subject: [PATCH] (v3.0.0.9003) eucast_rules fix, new tidymodels integration --- DESCRIPTION | 6 +- NAMESPACE | 14 ++ NEWS.md | 13 +- R/aa_helper_functions.R | 4 +- R/ab.R | 4 +- R/age.R | 2 +- R/data.R | 12 ++ R/eucast_rules.R | 31 ++-- R/mic.R | 8 +- R/random.R | 153 +++++++++-------- R/sir.R | 2 +- R/sysdata.rda | Bin 117988 -> 117988 bytes R/tidymodels.R | 262 ++++++++++++++++++++++++++++++ data-raw/_pre_commit_checks.R | 4 +- data/esbl_isolates.rda | Bin 0 -> 5284 bytes man/amr-tidymodels.Rd | 122 ++++++++++++++ man/as.sir.Rd | 2 +- man/esbl_isolates.Rd | 27 +++ man/random.Rd | 28 +++- tests/testthat/test-zzz.R | 18 ++ vignettes/AMR_with_tidymodels.Rmd | 153 ++++++++++++++++- vignettes/welcome_to_AMR.Rmd | 2 +- 22 files changed, 760 insertions(+), 107 deletions(-) create mode 100644 R/tidymodels.R create mode 100644 data/esbl_isolates.rda create mode 100644 man/amr-tidymodels.Rd create mode 100644 man/esbl_isolates.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 4499c0386..7ce982933 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: AMR -Version: 3.0.0.9002 -Date: 2025-06-06 +Version: 3.0.0.9003 +Date: 2025-06-13 Title: Antimicrobial Resistance Data Analysis Description: Functions to simplify and standardise antimicrobial resistance (AMR) data analysis and to work with microbial and antimicrobial properties by @@ -51,6 +51,8 @@ Suggests: pillar, progress, readxl, + recipes, + rlang, rmarkdown, rstudioapi, rvest, diff --git a/NAMESPACE b/NAMESPACE index 0cc72d821..2b2cb9f33 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -106,6 +106,8 @@ S3method(print,mo_uncertainties) S3method(print,pca) S3method(print,sir) S3method(print,sir_log) +S3method(print,step_mic_log2) +S3method(print,step_sir_numeric) S3method(quantile,mic) S3method(rep,ab) S3method(rep,av) @@ -159,6 +161,10 @@ export(administrable_per_os) export(age) export(age_groups) export(all_antimicrobials) +export(all_mic) +export(all_mic_predictors) +export(all_sir) +export(all_sir_predictors) export(aminoglycosides) export(aminopenicillins) export(amr_class) @@ -352,6 +358,8 @@ export(sir_df) export(sir_interpretation_history) export(sir_predict) export(skewness) +export(step_mic_log2) +export(step_sir_numeric) export(streptogramins) export(sulfonamides) export(susceptibility) @@ -388,6 +396,12 @@ if(getRversion() >= "3.0.0") S3method(pillar::type_sum, av) if(getRversion() >= "3.0.0") S3method(pillar::type_sum, mic) if(getRversion() >= "3.0.0") S3method(pillar::type_sum, mo) if(getRversion() >= "3.0.0") S3method(pillar::type_sum, sir) +if(getRversion() >= "3.0.0") S3method(recipes::bake, step_mic_log2) +if(getRversion() >= "3.0.0") S3method(recipes::bake, step_sir_numeric) +if(getRversion() >= "3.0.0") S3method(recipes::prep, step_mic_log2) +if(getRversion() >= "3.0.0") S3method(recipes::prep, step_sir_numeric) +if(getRversion() >= "3.0.0") S3method(recipes::tidy, step_mic_log2) +if(getRversion() >= "3.0.0") S3method(recipes::tidy, step_sir_numeric) if(getRversion() >= "3.0.0") S3method(skimr::get_skimmers, disk) if(getRversion() >= "3.0.0") S3method(skimr::get_skimmers, mic) if(getRversion() >= "3.0.0") S3method(skimr::get_skimmers, mo) diff --git a/NEWS.md b/NEWS.md index 2ee6d61e9..1eff949ac 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,17 @@ -# AMR 3.0.0.9002 +# AMR 3.0.0.9003 + +### New +* Integration with the **tidymodels** framework to allow seamless use of MIC and SIR data in modelling pipelines via `recipes` + - `step_mic_log2()` to transform `` columns with log2, and `step_sir_numeric()` to convert `` columns to numeric + - `tidyselect` helpers: `all_mic()`, `all_mic_predictors()`, `all_sir()`, `all_sir_predictors()` + - Enables seamless use of MIC and SIR data in modelling pipelines via `recipes` ### Changed -* Fix for `antibiogram()` for when no antimicrobials are set +* Fixed a bug in `antibiogram()` for when no antimicrobials are set +* Fixed a bug in `as.ab()` for antimicrobial codes with a number in it if they are preceded by a space +* Fixed a bug in `eucast_rules()` for using specific custom rules * Fixed some specific Dutch translations for antimicrobials +* Updated `random_mic()` and `random_disk()` to set skewedness of the distribution and allow multiple microorganisms # AMR 3.0.0 diff --git a/R/aa_helper_functions.R b/R/aa_helper_functions.R index d2566b44f..2aa98cb43 100644 --- a/R/aa_helper_functions.R +++ b/R/aa_helper_functions.R @@ -1244,7 +1244,9 @@ try_colour <- function(..., before, after, collapse = " ") { } } is_dark <- function() { - if (is.null(AMR_env$is_dark_theme)) { + AMR_env$current_theme <- tryCatch(getExportedValue("getThemeInfo", ns = asNamespace("rstudioapi"))()$editor, error = function(e) NULL) + if (!identical(AMR_env$current_theme, AMR_env$former_theme) || is.null(AMR_env$is_dark_theme)) { + AMR_env$former_theme <- AMR_env$current_theme AMR_env$is_dark_theme <- !has_colour() || tryCatch(isTRUE(getExportedValue("getThemeInfo", ns = asNamespace("rstudioapi"))()$dark), error = function(e) FALSE) } isTRUE(AMR_env$is_dark_theme) diff --git a/R/ab.R b/R/ab.R index 0fbe7b690..07102f12f 100755 --- a/R/ab.R +++ b/R/ab.R @@ -655,7 +655,9 @@ generalise_antibiotic_name <- function(x) { x <- trimws(gsub(" +", " ", x, perl = TRUE)) # remove last couple of words if they numbers or units x <- gsub("( ([0-9]{3,}|U?M?C?G|L))+$", "", x, perl = TRUE) - # move HIGH to end + # remove whitespace prior to numbers if preceded by A-Z + x <- gsub("([A-Z]+) +([0-9]+)", "\\1\\2", x, perl = TRUE) + # move HIGH to the end x <- trimws(gsub("(.*) HIGH(.*)", "\\1\\2 HIGH", x, perl = TRUE)) x } diff --git a/R/age.R b/R/age.R index 66f4a7823..903fc380d 100755 --- a/R/age.R +++ b/R/age.R @@ -208,7 +208,7 @@ age_groups <- function(x, split_at = c(12, 25, 55, 75), na.rm = FALSE) { split_at <- c(0, split_at) } split_at <- split_at[!is.na(split_at)] - stop_if(length(split_at) == 1, "invalid value for `split_at`") # only 0 is available + stop_if(length(split_at) == 1, "invalid value for `split_at`.") # only 0 is available # turn input values to 'split_at' indices y <- x diff --git a/R/data.R b/R/data.R index 73321c40b..bb6bfec3d 100755 --- a/R/data.R +++ b/R/data.R @@ -361,3 +361,15 @@ #' @examples #' dosage "dosage" + +#' Data Set with `r format(nrow(esbl_isolates), big.mark = " ")` ESBL Isolates +#' +#' A data set containing `r format(nrow(esbl_isolates), big.mark = " ")` microbial isolates with MIC values of common antibiotics and a binary `esbl` column for extended-spectrum beta-lactamase (ESBL) production. This data set contains randomised fictitious data but reflects reality and can be used to practise AMR-related machine learning, e.g., classification modelling with [tidymodels](https://amr-for-r.org/articles/AMR_with_tidymodels.html). +#' @format A [tibble][tibble::tibble] with `r format(nrow(esbl_isolates), big.mark = " ")` observations and `r ncol(esbl_isolates)` variables: +#' - `esbl`\cr Logical indicator if the isolate is ESBL-producing +#' - `genus`\cr Genus of the microorganism +#' - `AMC:COL`\cr MIC values for 17 antimicrobial agents, transformed to class [`mic`] (see [as.mic()]) +#' @details See our [tidymodels integration][amr-tidymodels] for an example using this data set. +#' @examples +#' esbl_isolates +"esbl_isolates" diff --git a/R/eucast_rules.R b/R/eucast_rules.R index 07f2a6816..18ec5e9f4 100755 --- a/R/eucast_rules.R +++ b/R/eucast_rules.R @@ -442,7 +442,7 @@ eucast_rules <- function(x, # big speed gain! only analyse unique rows: pm_distinct(`.rowid`, .keep_all = TRUE) %pm>% as.data.frame(stringsAsFactors = FALSE) - x[, col_mo] <- as.mo(as.character(x[, col_mo, drop = TRUE]), info = info) + x[, col_mo] <- as.mo(as.character(x[, col_mo, drop = TRUE]), info = FALSE) # rename col_mo to prevent interference with joined columns colnames(x)[colnames(x) == col_mo] <- ".col_mo" col_mo <- ".col_mo" @@ -450,8 +450,8 @@ eucast_rules <- function(x, x <- left_join_microorganisms(x, by = col_mo, suffix = c("_oldcols", "")) x$gramstain <- mo_gramstain(x[, col_mo, drop = TRUE], language = NULL, info = FALSE) x$genus_species <- trimws(paste(x$genus, x$species)) - if (isTRUE(info) && NROW(x) > 10000) { - message_(" OK.", add_fn = list(font_green, font_bold), as_note = FALSE) + if (isTRUE(info) && NROW(x.bak) > 10000) { + message_("OK.", add_fn = list(font_green, font_bold), as_note = FALSE) } n_added <- 0 @@ -624,31 +624,16 @@ eucast_rules <- function(x, eucast_rules_df <- eucast_rules_df %pm>% rbind_AMR(eucast_rules_df_total %pm>% subset(reference.rule_group %like% "breakpoint" & reference.version == version_breakpoints)) - # eucast_rules_df <- subset( - # eucast_rules_df, - # reference.rule_group %unlike% "breakpoint" | - # (reference.rule_group %like% "breakpoint" & reference.version == version_breakpoints) - # ) } if (any(c("all", "expected_phenotypes") %in% rules)) { eucast_rules_df <- eucast_rules_df %pm>% rbind_AMR(eucast_rules_df_total %pm>% subset(reference.rule_group %like% "expected" & reference.version == version_expected_phenotypes)) - # eucast_rules_df <- subset( - # eucast_rules_df, - # reference.rule_group %unlike% "expected" | - # (reference.rule_group %like% "expected" & reference.version == version_expected_phenotypes) - # ) } if (any(c("all", "expert") %in% rules)) { eucast_rules_df <- eucast_rules_df %pm>% rbind_AMR(eucast_rules_df_total %pm>% subset(reference.rule_group %like% "expert" & reference.version == version_expertrules)) - # eucast_rules_df <- subset( - # eucast_rules_df, - # reference.rule_group %unlike% "expert" | - # (reference.rule_group %like% "expert" & reference.version == version_expertrules) - # ) } ## filter out AmpC de-repressed cephalosporin-resistant mutants ---- # no need to filter on version number here - the rules contain these version number, so are inherently filtered @@ -671,6 +656,9 @@ eucast_rules <- function(x, # we only hints on remaining rows in `eucast_rules_df` screening_abx <- as.character(AMR::antimicrobials$ab[which(AMR::antimicrobials$ab %like% "-S$")]) screening_abx <- screening_abx[screening_abx %in% unique(unlist(strsplit(EUCAST_RULES_DF$and_these_antibiotics[!is.na(EUCAST_RULES_DF$and_these_antibiotics)], ", *")))] + if (isTRUE(info)) { + cat("\n") + } for (ab_s in screening_abx) { ab <- gsub("-S$", "", ab_s) if (ab %in% names(cols_ab) && !ab_s %in% names(cols_ab)) { @@ -901,7 +889,9 @@ eucast_rules <- function(x, } for (i in seq_len(length(custom_rules))) { rule <- custom_rules[[i]] - rows <- which(eval(parse(text = rule$query), envir = x)) + rows <- tryCatch(which(eval(parse(text = rule$query), envir = x)), + error = function(e) stop_(paste0(conditionMessage(e), font_red(" (check available data and compare with the custom rules set)")), call = FALSE) + ) cols <- as.character(rule$result_group) cols <- c( cols[cols %in% colnames(x)], # direct column names @@ -915,9 +905,8 @@ eucast_rules <- function(x, get_antibiotic_names(cols) ) if (isTRUE(info)) { - # print rule cat(italicise_taxonomy( - word_wrap(format_custom_query_rule(rule$query, colours = FALSE), + word_wrap(rule_text, width = getOption("width") - 30, extra_indent = 6 ), diff --git a/R/mic.R b/R/mic.R index 666acc014..591ca60bb 100644 --- a/R/mic.R +++ b/R/mic.R @@ -432,11 +432,17 @@ pillar_shaft.mic <- function(x, ...) { } crude_numbers <- as.double(x) operators <- gsub("[^<=>]+", "", as.character(x)) + # colourise operators operators[!is.na(operators) & operators != ""] <- font_silver(operators[!is.na(operators) & operators != ""], collapse = NULL) out <- trimws(paste0(operators, trimws(format(crude_numbers)))) out[is.na(x)] <- font_na(NA) # make trailing zeroes less visible - out[out %like% "[.]"] <- gsub("([.]?0+)$", font_silver("\\1"), out[out %like% "[.]"], perl = TRUE) + if (is_dark()) { + fn <- font_silver + } else { + fn <- font_white + } + out[out %like% "[.]"] <- gsub("([.]?0+)$", fn("\\1"), out[out %like% "[.]"], perl = TRUE) create_pillar_column(out, align = "right", width = max(nchar(font_stripstyle(out)))) } diff --git a/R/random.R b/R/random.R index bb99599f7..a5f003c2e 100755 --- a/R/random.R +++ b/R/random.R @@ -31,13 +31,17 @@ #' #' These functions can be used for generating random MIC values and disk diffusion diameters, for AMR data analysis practice. By providing a microorganism and antimicrobial drug, the generated results will reflect reality as much as possible. #' @param size Desired size of the returned vector. If used in a [data.frame] call or `dplyr` verb, will get the current (group) size if left blank. -#' @param mo Any [character] that can be coerced to a valid microorganism code with [as.mo()]. +#' @param mo Any [character] that can be coerced to a valid microorganism code with [as.mo()]. Can be the same length as `size`. #' @param ab Any [character] that can be coerced to a valid antimicrobial drug code with [as.ab()]. #' @param prob_SIR A vector of length 3: the probabilities for "S" (1st value), "I" (2nd value) and "R" (3rd value). +#' @param skew Direction of skew for MIC or disk values, either `"right"` or `"left"`. A left-skewed distribution has the majority of the data on the right. +#' @param severity Skew severity; higher values will increase the skewedness. Default is `2`; use `0` to prevent skewedness. #' @param ... Ignored, only in place to allow future extensions. -#' @details The base \R function [sample()] is used for generating values. -#' -#' Generated values are based on the EUCAST `r max(as.integer(gsub("[^0-9]", "", subset(clinical_breakpoints, guideline %like% "EUCAST")$guideline)))` guideline as implemented in the [clinical_breakpoints] data set. To create specific generated values per bug or drug, set the `mo` and/or `ab` argument. +#' @details +#' Internally, MIC and disk zone values are sampled based on clinical breakpoints defined in the [clinical_breakpoints] data set. To create specific generated values per bug or drug, set the `mo` and/or `ab` argument. The MICs are sampled on a log2 scale and disks linearly, using weighted probabilities. The weights are based on the `skew` and `severity` arguments: +#' * `skew = "right"` places more emphasis on lower MIC or higher disk values. +#' * `skew = "left"` places more emphasis on higher MIC or lower disk values. +#' * `severity` controls the exponential bias applied. #' @return class `mic` for [random_mic()] (see [as.mic()]) and class `disk` for [random_disk()] (see [as.disk()]) #' @name random #' @rdname random @@ -47,8 +51,13 @@ #' random_disk(25) #' random_sir(25) #' +#' # add more skewedness, make more realistic by setting a bug and/or drug: +#' disks <- random_disk(100, severity = 2, mo = "Escherichia coli", ab = "CIP") +#' plot(disks) +#' # `plot()` and `ggplot2::autoplot()` allow for coloured bars if `mo` and `ab` are set +#' plot(disks, mo = "Escherichia coli", ab = "CIP", guideline = "CLSI 2025") +#' #' \donttest{ -#' # make the random generation more realistic by setting a bug and/or drug: #' random_mic(25, "Klebsiella pneumoniae") # range 0.0625-64 #' random_mic(25, "Klebsiella pneumoniae", "meropenem") # range 0.0625-16 #' random_mic(25, "Streptococcus pneumoniae", "meropenem") # range 0.0625-4 @@ -57,26 +66,60 @@ #' random_disk(25, "Klebsiella pneumoniae", "ampicillin") # range 11-17 #' random_disk(25, "Streptococcus pneumoniae", "ampicillin") # range 12-27 #' } -random_mic <- function(size = NULL, mo = NULL, ab = NULL, ...) { +random_mic <- function(size = NULL, mo = NULL, ab = NULL, skew = "right", severity = 1, ...) { meet_criteria(size, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE, allow_NULL = TRUE) - meet_criteria(mo, allow_class = "character", has_length = 1, allow_NULL = TRUE) + meet_criteria(mo, allow_class = "character", has_length = c(1, size), allow_NULL = TRUE) meet_criteria(ab, allow_class = "character", has_length = 1, allow_NULL = TRUE) + meet_criteria(skew, allow_class = "character", is_in = c("right", "left"), has_length = 1) + meet_criteria(severity, allow_class = c("numeric", "integer"), has_length = 1, is_positive_or_zero = TRUE, is_finite = TRUE) + if (is.null(size)) { size <- NROW(get_current_data(arg_name = "size", call = -3)) } - random_exec("MIC", size = size, mo = mo, ab = ab) + if (length(mo) > 1) { + out <- rep(NA_mic_, length(size)) + p <- progress_ticker(n = length(unique(mo)), n_min = 10, title = "Generating random MIC values") + for (mo_ in unique(mo)) { + p$tick() + out[which(mo == mo_)] <- random_exec("MIC", size = sum(mo == mo_), mo = mo_, ab = ab, skew = skew, severity = severity) + } + out <- as.mic(out, keep_operators = "none") + if (stats::runif(1) > 0.5 && length(unique(out)) > 1) { + out[out == min(out)] <- paste0("<=", out[out == min(out)]) + } + if (stats::runif(1) > 0.5 && length(unique(out)) > 1) { + out[out == max(out)] <- paste0(">=", out[out == max(out)]) + } + return(out) + } else { + random_exec("MIC", size = size, mo = mo, ab = ab, skew = skew, severity = severity) + } } #' @rdname random #' @export -random_disk <- function(size = NULL, mo = NULL, ab = NULL, ...) { +random_disk <- function(size = NULL, mo = NULL, ab = NULL, skew = "left", severity = 1, ...) { meet_criteria(size, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE, allow_NULL = TRUE) - meet_criteria(mo, allow_class = "character", has_length = 1, allow_NULL = TRUE) + meet_criteria(mo, allow_class = "character", has_length = c(1, size), allow_NULL = TRUE) meet_criteria(ab, allow_class = "character", has_length = 1, allow_NULL = TRUE) + meet_criteria(skew, allow_class = "character", is_in = c("right", "left"), has_length = 1) + meet_criteria(severity, allow_class = c("numeric", "integer"), has_length = 1, is_positive_or_zero = TRUE, is_finite = TRUE) + if (is.null(size)) { size <- NROW(get_current_data(arg_name = "size", call = -3)) } - random_exec("DISK", size = size, mo = mo, ab = ab) + if (length(mo) > 1) { + out <- rep(NA_mic_, length(size)) + p <- progress_ticker(n = length(unique(mo)), n_min = 10, title = "Generating random MIC values") + for (mo_ in unique(mo)) { + p$tick() + out[which(mo == mo_)] <- random_exec("DISK", size = sum(mo == mo_), mo = mo_, ab = ab, skew = skew, severity = severity) + } + out <- as.disk(out) + return(out) + } else { + random_exec("DISK", size = size, mo = mo, ab = ab, skew = skew, severity = severity) + } } #' @rdname random @@ -90,78 +133,60 @@ random_sir <- function(size = NULL, prob_SIR = c(0.33, 0.33, 0.33), ...) { sample(as.sir(c("S", "I", "R")), size = size, replace = TRUE, prob = prob_SIR) } -random_exec <- function(method_type, size, mo = NULL, ab = NULL) { - df <- AMR::clinical_breakpoints %pm>% - pm_filter(guideline %like% "EUCAST") %pm>% - pm_arrange(pm_desc(guideline)) %pm>% - subset(guideline == max(guideline) & - method == method_type & - type == "human") + +random_exec <- function(method_type, size, mo = NULL, ab = NULL, skew = "right", severity = 1) { + df <- AMR::clinical_breakpoints %pm>% subset(method == method_type & type == "human") if (!is.null(mo)) { - mo_coerced <- as.mo(mo) - mo_include <- c( - mo_coerced, - as.mo(mo_genus(mo_coerced)), - as.mo(mo_family(mo_coerced)), - as.mo(mo_order(mo_coerced)) - ) - df_new <- df %pm>% - subset(mo %in% mo_include) - if (nrow(df_new) > 0) { - df <- df_new - } else { - warning_("in `random_", tolower(method_type), "()`: no rows found that match mo '", mo, "', ignoring argument `mo`") - } + mo_coerced <- as.mo(mo, info = FALSE) + mo_include <- c(mo_coerced, as.mo(mo_genus(mo_coerced)), as.mo(mo_family(mo_coerced)), as.mo(mo_order(mo_coerced))) + df_new <- df %pm>% subset(mo %in% mo_include) + if (nrow(df_new) > 0) df <- df_new } if (!is.null(ab)) { ab_coerced <- as.ab(ab) - df_new <- df %pm>% - subset(ab %in% ab_coerced) - if (nrow(df_new) > 0) { - df <- df_new - } else { - warning_("in `random_", tolower(method_type), "()`: no rows found that match ab '", ab, "' (", ab_name(ab_coerced, tolower = TRUE, language = NULL), "), ignoring argument `ab`") - } + df_new <- df %pm>% subset(ab %in% ab_coerced) + if (nrow(df_new) > 0) df <- df_new } if (method_type == "MIC") { - # set range - mic_range <- c(0.001, 0.002, 0.005, 0.010, 0.025, 0.0625, 0.125, 0.250, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256) + lowest_mic <- min(df$breakpoint_S, na.rm = TRUE) + lowest_mic <- log2(lowest_mic) + sample(c(-3:2), 1) + lowest_mic <- 2^lowest_mic + highest_mic <- max(df$breakpoint_R, na.rm = TRUE) + highest_mic <- log2(highest_mic) + sample(c(-3:1), 1) + highest_mic <- max(lowest_mic * 2, 2^highest_mic) - # get highest/lowest +/- random 1 to 3 higher factors of two - max_range <- mic_range[min( - length(mic_range), - which(mic_range == max(df$breakpoint_R[!is.na(df$breakpoint_R)], na.rm = TRUE)) + sample(c(1:3), 1) - )] - min_range <- mic_range[max( - 1, - which(mic_range == min(df$breakpoint_S, na.rm = TRUE)) - sample(c(1:3), 1) - )] - - mic_range_new <- mic_range[mic_range <= max_range & mic_range >= min_range] - if (length(mic_range_new) == 0) { - mic_range_new <- mic_range - } - out <- as.mic(sample(mic_range_new, size = size, replace = TRUE)) - # 50% chance that lowest will get <= and highest will get >= + out <- skewed_values(COMMON_MIC_VALUES, size = size, min = lowest_mic, max = highest_mic, skew = skew, severity = severity) if (stats::runif(1) > 0.5 && length(unique(out)) > 1) { out[out == min(out)] <- paste0("<=", out[out == min(out)]) } if (stats::runif(1) > 0.5 && length(unique(out)) > 1) { out[out == max(out)] <- paste0(">=", out[out == max(out)]) } - return(out) + return(as.mic(out)) } else if (method_type == "DISK") { - set_range <- seq( - from = as.integer(min(df$breakpoint_R[!is.na(df$breakpoint_R)], na.rm = TRUE) / 1.25), - to = as.integer(max(df$breakpoint_S, na.rm = TRUE) * 1.25), + disk_range <- seq( + from = floor(min(df$breakpoint_R[!is.na(df$breakpoint_R)], na.rm = TRUE) / 1.25), + to = ceiling(max(df$breakpoint_S[df$breakpoint_S != 50], na.rm = TRUE) * 1.25), by = 1 ) - out <- sample(set_range, size = size, replace = TRUE) - out[out < 6] <- sample(c(6:10), length(out[out < 6]), replace = TRUE) - out[out > 50] <- sample(c(40:50), length(out[out > 50]), replace = TRUE) + disk_range <- disk_range[disk_range >= 6 & disk_range <= 50] + out <- skewed_values(disk_range, size = size, min = min(disk_range), max = max(disk_range), skew = skew, severity = severity) return(as.disk(out)) } } + +skewed_values <- function(values, size, min, max, skew = c("right", "left"), severity = 1) { + skew <- match.arg(skew) + range_vals <- values[values >= min & values <= max] + if (length(range_vals) < 2) range_vals <- values + ranks <- seq_along(range_vals) + weights <- switch(skew, + right = rev(ranks)^severity, + left = ranks^severity + ) + weights <- weights / sum(weights) + sample(range_vals, size = size, replace = TRUE, prob = weights) +} diff --git a/R/sir.R b/R/sir.R index 9cd03b156..a0647a4b4 100755 --- a/R/sir.R +++ b/R/sir.R @@ -159,7 +159,7 @@ #' #' The function [is.sir()] detects if the input contains class `sir`. If the input is a [data.frame] or [list], it iterates over all columns/items and returns a [logical] vector. #' -#' The base R function [as.double()] can be used to retrieve quantitative values from a `sir` object: `"S"` = 1, `"I"`/`"SDD"` = 2, `"R"` = 3. All other values are rendered `NA` . **Note:** Do not use `as.integer()`, since that (because of how R works internally) will return the factor level indices, and not these aforementioned quantitative values. +#' The base R function [as.double()] can be used to retrieve quantitative values from a `sir` object: `"S"` = 1, `"I"`/`"SDD"` = 2, `"R"` = 3. All other values are rendered `NA`. **Note:** Do not use `as.integer()`, since that (because of how R works internally) will return the factor level indices, and not these aforementioned quantitative values. #' #' The function [is_sir_eligible()] returns `TRUE` when a column contains at most 5% potentially invalid antimicrobial interpretations, and `FALSE` otherwise. The threshold of 5% can be set with the `threshold` argument. If the input is a [data.frame], it iterates over all columns and returns a [logical] vector. #' @section Interpretation of SIR: diff --git a/R/sysdata.rda b/R/sysdata.rda index 0094643ea42cd4e6a0188e287c0e8183147850fc..0b9dce5413e78d2e58f4d7c76c5b144299aa6c5e 100755 GIT binary patch delta 53889 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 delta 53889 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 diff --git a/R/tidymodels.R b/R/tidymodels.R new file mode 100644 index 000000000..a5722e568 --- /dev/null +++ b/R/tidymodels.R @@ -0,0 +1,262 @@ +#' AMR Extensions for Tidymodels +#' +#' This family of functions allows using AMR-specific data types such as `` and `` inside `tidymodels` pipelines. +#' @inheritParams recipes::step_center +#' @details +#' You can read more in our online [AMR with tidymodels introduction](https://amr-for-r.org/articles/AMR_with_tidymodels.html). +#' +#' Tidyselect helpers include: +#' - [all_mic()] and [all_mic_predictors()] to select `` columns +#' - [all_sir()] and [all_sir_predictors()] to select `` columns +#' +#' Pre-processing pipeline steps include: +#' - [step_mic_log2()] to convert MIC columns to numeric (via `as.numeric()`) and apply a log2 transform, to be used with [all_mic_predictors()] +#' - [step_sir_numeric()] to convert SIR columns to numeric (via `as.numeric()`), to be used with [all_sir_predictors()]: `"S"` = 1, `"I"`/`"SDD"` = 2, `"R"` = 3. All other values are rendered `NA`. Keep this in mind for further processing, especially if the model does not allow for `NA` values. +#' +#' These steps integrate with `recipes::recipe()` and work like standard preprocessing steps. They are useful for preparing data for modelling, especially with classification models. +#' @seealso [recipes::recipe()], [as.mic()], [as.sir()] +#' @name amr-tidymodels +#' @keywords internal +#' @export +#' @examples +#' library(tidymodels) +#' +#' # The below approach formed the basis for this paper: DOI 10.3389/fmicb.2025.1582703 +#' # Presence of ESBL genes was predicted based on raw MIC values. +#' +#' +#' # example data set in the AMR package +#' esbl_isolates +#' +#' # Prepare a binary outcome and convert to ordered factor +#' data <- esbl_isolates %>% +#' mutate(esbl = factor(esbl, levels = c(FALSE, TRUE), ordered = TRUE)) +#' +#' # Split into training and testing sets +#' split <- initial_split(data) +#' training_data <- training(split) +#' testing_data <- testing(split) +#' +#' # Create and prep a recipe with MIC log2 transformation +#' mic_recipe <- recipe(esbl ~ ., data = training_data) %>% +#' # Optionally remove non-predictive variables +#' remove_role(genus, old_role = "predictor") %>% +#' # Apply the log2 transformation to all MIC predictors +#' step_mic_log2(all_mic_predictors()) %>% +#' prep() +#' +#' # View prepped recipe +#' mic_recipe +#' +#' # Apply the recipe to training and testing data +#' out_training <- bake(mic_recipe, new_data = NULL) +#' out_testing <- bake(mic_recipe, new_data = testing_data) +#' +#' # Fit a logistic regression model +#' fitted <- logistic_reg(mode = "classification") %>% +#' set_engine("glm") %>% +#' fit(esbl ~ ., data = out_training) +#' +#' # Generate predictions on the test set +#' predictions <- predict(fitted, out_testing) %>% +#' bind_cols(out_testing) +#' +#' # Evaluate predictions using standard classification metrics +#' our_metrics <- metric_set(accuracy, kap, ppv, npv) +#' metrics <- our_metrics(predictions, truth = esbl, estimate = .pred_class) +#' +#' # Show performance: +#' # - negative predictive value (NPV) of ~98% +#' # - positive predictive value (PPV) of ~94% +#' metrics +all_mic <- function() { + x <- tidymodels_amr_select(levels(NA_mic_)) + names(x) +} + +#' @rdname amr-tidymodels +#' @export +all_mic_predictors <- function() { + x <- tidymodels_amr_select(levels(NA_mic_)) + intersect(x, recipes::has_role("predictor")) +} + +#' @rdname amr-tidymodels +#' @export +all_sir <- function() { + x <- tidymodels_amr_select(levels(NA_sir_)) + names(x) +} + +#' @rdname amr-tidymodels +#' @export +all_sir_predictors <- function() { + x <- tidymodels_amr_select(levels(NA_sir_)) + intersect(x, recipes::has_role("predictor")) +} + +#' @rdname amr-tidymodels +#' @export +step_mic_log2 <- function( + recipe, + ..., + role = NA, + trained = FALSE, + columns = NULL, + skip = FALSE, + id = recipes::rand_id("mic_log2")) { + recipes::add_step( + recipe, + step_mic_log2_new( + terms = rlang::enquos(...), + role = role, + trained = trained, + columns = columns, + skip = skip, + id = id + ) + ) +} + +step_mic_log2_new <- function(terms, role, trained, columns, skip, id) { + recipes::step( + subclass = "mic_log2", + terms = terms, + role = role, + trained = trained, + columns = columns, + skip = skip, + id = id + ) +} + +#' @rawNamespace if(getRversion() >= "3.0.0") S3method(recipes::prep, step_mic_log2) +prep.step_mic_log2 <- function(x, training, info = NULL, ...) { + col_names <- recipes::recipes_eval_select(x$terms, training, info) + recipes::check_type(training[, col_names], types = "ordered") + step_mic_log2_new( + terms = x$terms, + role = x$role, + trained = TRUE, + columns = col_names, + skip = x$skip, + id = x$id + ) +} + +#' @rawNamespace if(getRversion() >= "3.0.0") S3method(recipes::bake, step_mic_log2) +bake.step_mic_log2 <- function(object, new_data, ...) { + recipes::check_new_data(object$columns, object, new_data) + for (col in object$columns) { + new_data[[col]] <- log2(as.numeric(as.mic(new_data[[col]]))) + } + new_data +} + +#' @export +print.step_mic_log2 <- function(x, width = max(20, options()$width - 35), ...) { + title <- "Log2 transformation of MIC columns" + recipes::print_step(x$columns, x$terms, x$trained, title, width) + invisible(x) +} + +#' @rawNamespace if(getRversion() >= "3.0.0") S3method(recipes::tidy, step_mic_log2) +tidy.step_mic_log2 <- function(x, ...) { + if (recipes::is_trained(x)) { + res <- tibble::tibble(terms = x$columns) + } else { + res <- tibble::tibble(terms = recipes::sel2char(x$terms)) + } + res$id <- x$id + res +} + +#' @rdname amr-tidymodels +#' @export +step_sir_numeric <- function( + recipe, + ..., + role = NA, + trained = FALSE, + columns = NULL, + skip = FALSE, + id = recipes::rand_id("sir_numeric")) { + recipes::add_step( + recipe, + step_sir_numeric_new( + terms = rlang::enquos(...), + role = role, + trained = trained, + columns = columns, + skip = skip, + id = id + ) + ) +} + +step_sir_numeric_new <- function(terms, role, trained, columns, skip, id) { + recipes::step( + subclass = "sir_numeric", + terms = terms, + role = role, + trained = trained, + columns = columns, + skip = skip, + id = id + ) +} + +#' @rawNamespace if(getRversion() >= "3.0.0") S3method(recipes::prep, step_sir_numeric) +prep.step_sir_numeric <- function(x, training, info = NULL, ...) { + col_names <- recipes::recipes_eval_select(x$terms, training, info) + recipes::check_type(training[, col_names], types = "ordered") + step_sir_numeric_new( + terms = x$terms, + role = x$role, + trained = TRUE, + columns = col_names, + skip = x$skip, + id = x$id + ) +} + +#' @rawNamespace if(getRversion() >= "3.0.0") S3method(recipes::bake, step_sir_numeric) +bake.step_sir_numeric <- function(object, new_data, ...) { + recipes::check_new_data(object$columns, object, new_data) + for (col in object$columns) { + new_data[[col]] <- as.numeric(as.sir(new_data[[col]])) + } + new_data +} + +#' @export +print.step_sir_numeric <- function(x, width = max(20, options()$width - 35), ...) { + title <- "Numeric transformation of SIR columns" + recipes::print_step(x$columns, x$terms, x$trained, title, width) + invisible(x) +} + +#' @rawNamespace if(getRversion() >= "3.0.0") S3method(recipes::tidy, step_sir_numeric) +tidy.step_sir_numeric <- function(x, ...) { + if (recipes::is_trained(x)) { + res <- tibble::tibble(terms = x$columns) + } else { + res <- tibble::tibble(terms = recipes::sel2char(x$terms)) + } + res$id <- x$id + res +} + +tidymodels_amr_select <- function(check_vector) { + df <- get_current_data() + ind <- which( + vapply( + FUN.VALUE = logical(1), + df, + function(x) all(x %in% c(check_vector, NA), na.rm = TRUE) & any(x %in% check_vector), + USE.NAMES = TRUE + ), + useNames = TRUE + ) + ind +} diff --git a/data-raw/_pre_commit_checks.R b/data-raw/_pre_commit_checks.R index bf626fc68..84e73e9f5 100644 --- a/data-raw/_pre_commit_checks.R +++ b/data-raw/_pre_commit_checks.R @@ -663,7 +663,9 @@ if (files_changed()) { } # Update index.md and README.md ------------------------------------------- -if (files_changed("man/microorganisms.Rd") || +if (files_changed("README.Rmd") || + files_changed("index.Rmd") || + files_changed("man/microorganisms.Rd") || files_changed("man/antimicrobials.Rd") || files_changed("man/clinical_breakpoints.Rd") || files_changed("man/antibiogram.Rd") || diff --git a/data/esbl_isolates.rda b/data/esbl_isolates.rda new file mode 100644 index 0000000000000000000000000000000000000000..2f704a2a8ae9f818206e934bc432fa2da00979a8 GIT binary patch literal 5284 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 literal 0 HcmV?d00001 diff --git a/man/amr-tidymodels.Rd b/man/amr-tidymodels.Rd new file mode 100644 index 000000000..b79239ae5 --- /dev/null +++ b/man/amr-tidymodels.Rd @@ -0,0 +1,122 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tidymodels.R +\name{amr-tidymodels} +\alias{amr-tidymodels} +\alias{all_mic} +\alias{all_mic_predictors} +\alias{all_sir} +\alias{all_sir_predictors} +\alias{step_mic_log2} +\alias{step_sir_numeric} +\title{AMR Extensions for Tidymodels} +\usage{ +all_mic() + +all_mic_predictors() + +all_sir() + +all_sir_predictors() + +step_mic_log2(recipe, ..., role = NA, trained = FALSE, columns = NULL, + skip = FALSE, id = recipes::rand_id("mic_log2")) + +step_sir_numeric(recipe, ..., role = NA, trained = FALSE, columns = NULL, + skip = FALSE, id = recipes::rand_id("sir_numeric")) +} +\arguments{ +\item{recipe}{A recipe object. The step will be added to the sequence of +operations for this recipe.} + +\item{...}{One or more selector functions to choose variables for this step. +See \code{\link[recipes:selections]{selections()}} for more details.} + +\item{role}{Not used by this step since no new variables are created.} + +\item{trained}{A logical to indicate if the quantities for preprocessing have +been estimated.} + +\item{skip}{A logical. Should the step be skipped when the recipe is baked by +\code{\link[recipes:bake]{bake()}}? While all operations are baked when \code{\link[recipes:prep]{prep()}} is run, some +operations may not be able to be conducted on new data (e.g. processing the +outcome variable(s)). Care should be taken when using \code{skip = TRUE} as it +may affect the computations for subsequent operations.} + +\item{id}{A character string that is unique to this step to identify it.} +} +\description{ +This family of functions allows using AMR-specific data types such as \verb{} and \verb{} inside \code{tidymodels} pipelines. +} +\details{ +You can read more in our online \href{https://amr-for-r.org/articles/AMR_with_tidymodels.html}{AMR with tidymodels introduction}. + +Tidyselect helpers include: +\itemize{ +\item \code{\link[=all_mic]{all_mic()}} and \code{\link[=all_mic_predictors]{all_mic_predictors()}} to select \verb{} columns +\item \code{\link[=all_sir]{all_sir()}} and \code{\link[=all_sir_predictors]{all_sir_predictors()}} to select \verb{} columns +} + +Pre-processing pipeline steps include: +\itemize{ +\item \code{\link[=step_mic_log2]{step_mic_log2()}} to convert MIC columns to numeric (via \code{as.numeric()}) and apply a log2 transform, to be used with \code{\link[=all_mic_predictors]{all_mic_predictors()}} +\item \code{\link[=step_sir_numeric]{step_sir_numeric()}} to convert SIR columns to numeric (via \code{as.numeric()}), to be used with \code{\link[=all_sir_predictors]{all_sir_predictors()}}: \code{"S"} = 1, \code{"I"}/\code{"SDD"} = 2, \code{"R"} = 3. All other values are rendered \code{NA}. Keep this in mind for further processing, especially if the model does not allow for \code{NA} values. +} + +These steps integrate with \code{recipes::recipe()} and work like standard preprocessing steps. They are useful for preparing data for modelling, especially with classification models. +} +\examples{ +library(tidymodels) + +# The below approach formed the basis for this paper: DOI 10.3389/fmicb.2025.1582703 +# Presence of ESBL genes was predicted based on raw MIC values. + + +# example data set in the AMR package +esbl_isolates + +# Prepare a binary outcome and convert to ordered factor +data <- esbl_isolates \%>\% + mutate(esbl = factor(esbl, levels = c(FALSE, TRUE), ordered = TRUE)) + +# Split into training and testing sets +split <- initial_split(data) +training_data <- training(split) +testing_data <- testing(split) + +# Create and prep a recipe with MIC log2 transformation +mic_recipe <- recipe(esbl ~ ., data = training_data) \%>\% + # Optionally remove non-predictive variables + remove_role(genus, old_role = "predictor") \%>\% + # Apply the log2 transformation to all MIC predictors + step_mic_log2(all_mic_predictors()) \%>\% + prep() + +# View prepped recipe +mic_recipe + +# Apply the recipe to training and testing data +out_training <- bake(mic_recipe, new_data = NULL) +out_testing <- bake(mic_recipe, new_data = testing_data) + +# Fit a logistic regression model +fitted <- logistic_reg(mode = "classification") \%>\% + set_engine("glm") \%>\% + fit(esbl ~ ., data = out_training) + +# Generate predictions on the test set +predictions <- predict(fitted, out_testing) \%>\% + bind_cols(out_testing) + +# Evaluate predictions using standard classification metrics +our_metrics <- metric_set(accuracy, kap, ppv, npv) +metrics <- our_metrics(predictions, truth = esbl, estimate = .pred_class) + +# Show performance: +# - negative predictive value (NPV) of ~98\% +# - positive predictive value (PPV) of ~94\% +metrics +} +\seealso{ +\code{\link[recipes:recipe]{recipes::recipe()}}, \code{\link[=as.mic]{as.mic()}}, \code{\link[=as.sir]{as.sir()}} +} +\keyword{internal} diff --git a/man/as.sir.Rd b/man/as.sir.Rd index 3e2d91725..9629e5b87 100644 --- a/man/as.sir.Rd +++ b/man/as.sir.Rd @@ -247,7 +247,7 @@ To determine which isolates are multi-drug resistant, be sure to run \code{\link The function \code{\link[=is.sir]{is.sir()}} detects if the input contains class \code{sir}. If the input is a \link{data.frame} or \link{list}, it iterates over all columns/items and returns a \link{logical} vector. -The base R function \code{\link[=as.double]{as.double()}} can be used to retrieve quantitative values from a \code{sir} object: \code{"S"} = 1, \code{"I"}/\code{"SDD"} = 2, \code{"R"} = 3. All other values are rendered \code{NA} . \strong{Note:} Do not use \code{as.integer()}, since that (because of how R works internally) will return the factor level indices, and not these aforementioned quantitative values. +The base R function \code{\link[=as.double]{as.double()}} can be used to retrieve quantitative values from a \code{sir} object: \code{"S"} = 1, \code{"I"}/\code{"SDD"} = 2, \code{"R"} = 3. All other values are rendered \code{NA}. \strong{Note:} Do not use \code{as.integer()}, since that (because of how R works internally) will return the factor level indices, and not these aforementioned quantitative values. The function \code{\link[=is_sir_eligible]{is_sir_eligible()}} returns \code{TRUE} when a column contains at most 5\% potentially invalid antimicrobial interpretations, and \code{FALSE} otherwise. The threshold of 5\% can be set with the \code{threshold} argument. If the input is a \link{data.frame}, it iterates over all columns and returns a \link{logical} vector. } diff --git a/man/esbl_isolates.Rd b/man/esbl_isolates.Rd new file mode 100644 index 000000000..a6433c08a --- /dev/null +++ b/man/esbl_isolates.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\docType{data} +\name{esbl_isolates} +\alias{esbl_isolates} +\title{Data Set with 500 ESBL Isolates} +\format{ +A \link[tibble:tibble]{tibble} with 500 observations and 19 variables: +\itemize{ +\item \code{esbl}\cr Logical indicator if the isolate is ESBL-producing +\item \code{genus}\cr Genus of the microorganism +\item \code{AMC:COL}\cr MIC values for 17 antimicrobial agents, transformed to class \code{\link{mic}} (see \code{\link[=as.mic]{as.mic()}}) +} +} +\usage{ +esbl_isolates +} +\description{ +A data set containing 500 microbial isolates with MIC values of common antibiotics and a binary \code{esbl} column for extended-spectrum beta-lactamase (ESBL) production. This data set contains randomised fictitious data but reflects reality and can be used to practise AMR-related machine learning, e.g., classification modelling with \href{https://amr-for-r.org/articles/AMR_with_tidymodels.html}{tidymodels}. +} +\details{ +See our \link[=amr-tidymodels]{tidymodels integration} for an example using this data set. +} +\examples{ +esbl_isolates +} +\keyword{datasets} diff --git a/man/random.Rd b/man/random.Rd index 29c1c1669..1a0ffef08 100644 --- a/man/random.Rd +++ b/man/random.Rd @@ -7,19 +7,25 @@ \alias{random_sir} \title{Random MIC Values/Disk Zones/SIR Generation} \usage{ -random_mic(size = NULL, mo = NULL, ab = NULL, ...) +random_mic(size = NULL, mo = NULL, ab = NULL, skew = "right", + severity = 1, ...) -random_disk(size = NULL, mo = NULL, ab = NULL, ...) +random_disk(size = NULL, mo = NULL, ab = NULL, skew = "left", + severity = 1, ...) random_sir(size = NULL, prob_SIR = c(0.33, 0.33, 0.33), ...) } \arguments{ \item{size}{Desired size of the returned vector. If used in a \link{data.frame} call or \code{dplyr} verb, will get the current (group) size if left blank.} -\item{mo}{Any \link{character} that can be coerced to a valid microorganism code with \code{\link[=as.mo]{as.mo()}}.} +\item{mo}{Any \link{character} that can be coerced to a valid microorganism code with \code{\link[=as.mo]{as.mo()}}. Can be the same length as \code{size}.} \item{ab}{Any \link{character} that can be coerced to a valid antimicrobial drug code with \code{\link[=as.ab]{as.ab()}}.} +\item{skew}{Direction of skew for MIC or disk values, either \code{"right"} or \code{"left"}. A left-skewed distribution has the majority of the data on the right.} + +\item{severity}{Skew severity; higher values will increase the skewedness. Default is \code{2}; use \code{0} to prevent skewedness.} + \item{...}{Ignored, only in place to allow future extensions.} \item{prob_SIR}{A vector of length 3: the probabilities for "S" (1st value), "I" (2nd value) and "R" (3rd value).} @@ -31,17 +37,25 @@ class \code{mic} for \code{\link[=random_mic]{random_mic()}} (see \code{\link[=a These functions can be used for generating random MIC values and disk diffusion diameters, for AMR data analysis practice. By providing a microorganism and antimicrobial drug, the generated results will reflect reality as much as possible. } \details{ -The base \R function \code{\link[=sample]{sample()}} is used for generating values. - -Generated values are based on the EUCAST 2025 guideline as implemented in the \link{clinical_breakpoints} data set. To create specific generated values per bug or drug, set the \code{mo} and/or \code{ab} argument. +Internally, MIC and disk zone values are sampled based on clinical breakpoints defined in the \link{clinical_breakpoints} data set. To create specific generated values per bug or drug, set the \code{mo} and/or \code{ab} argument. The MICs are sampled on a log2 scale and disks linearly, using weighted probabilities. The weights are based on the \code{skew} and \code{severity} arguments: +\itemize{ +\item \code{skew = "right"} places more emphasis on lower MIC or higher disk values. +\item \code{skew = "left"} places more emphasis on higher MIC or lower disk values. +\item \code{severity} controls the exponential bias applied. +} } \examples{ random_mic(25) random_disk(25) random_sir(25) +# add more skewedness, make more realistic by setting a bug and/or drug: +disks <- random_disk(100, severity = 2, mo = "Escherichia coli", ab = "CIP") +plot(disks) +# `plot()` and `ggplot2::autoplot()` allow for coloured bars if `mo` and `ab` are set +plot(disks, mo = "Escherichia coli", ab = "CIP", guideline = "CLSI 2025") + \donttest{ -# make the random generation more realistic by setting a bug and/or drug: random_mic(25, "Klebsiella pneumoniae") # range 0.0625-64 random_mic(25, "Klebsiella pneumoniae", "meropenem") # range 0.0625-16 random_mic(25, "Streptococcus pneumoniae", "meropenem") # range 0.0625-4 diff --git a/tests/testthat/test-zzz.R b/tests/testthat/test-zzz.R index d31ed2f86..ec6834cdd 100644 --- a/tests/testthat/test-zzz.R +++ b/tests/testthat/test-zzz.R @@ -127,6 +127,24 @@ test_that("test-zzz.R", { "type_sum" = "pillar", # readxl "read_excel" = "readxl", + # recipes + "add_step" = "recipes", + "bake" = "recipes", + "check_new_data" = "recipes", + "check_type" = "recipes", + "has_role" = "recipes", + "is_trained" = "recipes", + "prep" = "recipes", + "print_step" = "recipes", + "rand_id" = "recipes", + "recipe" = "recipes", + "recipes_eval_select" = "recipes", + "sel2char" = "recipes", + "step" = "recipes", + "step_center" = "recipes", + "tidy" = "recipes", + # rlang + "enquos" = "rlang", # rmarkdown "html_vignette" = "rmarkdown", # skimr diff --git a/vignettes/AMR_with_tidymodels.Rmd b/vignettes/AMR_with_tidymodels.Rmd index eca38f93f..3bb1b0529 100644 --- a/vignettes/AMR_with_tidymodels.Rmd +++ b/vignettes/AMR_with_tidymodels.Rmd @@ -26,7 +26,14 @@ knitr::opts_chunk$set( Antimicrobial resistance (AMR) is a global health crisis, and understanding resistance patterns is crucial for managing effective treatments. The `AMR` R package provides robust tools for analysing AMR data, including convenient antimicrobial selector functions like `aminoglycosides()` and `betalactams()`. -In this post, we will explore how to use the `tidymodels` framework to predict resistance patterns in the `example_isolates` dataset in two examples. +In this post, we will explore how to use the `tidymodels` framework to predict resistance patterns in the `example_isolates` dataset in two examples. + +This post contains the following examples: + +1. Using Antimicrobial Selectors +2. Predicting ESBL Presence Using Raw MICs +3. Predicting AMR Over Time + ## Example 1: Using Antimicrobial Selectors @@ -208,10 +215,150 @@ This workflow is extensible to other antimicrobial classes and resistance patter --- +## Example 2: Predicting ESBL Presence Using Raw MICs -## Example 2: Predicting AMR Over Time +In this second example, we demonstrate how to use `` columns directly in `tidymodels` workflows using AMR-specific recipe steps. This includes a transformation to `log2` scale using `step_mic_log2()`, which prepares MIC values for use in classification models. -In this second example, we aim to predict antimicrobial resistance (AMR) trends over time using `tidymodels`. We will model resistance to three antibiotics (amoxicillin `AMX`, amoxicillin-clavulanic acid `AMC`, and ciprofloxacin `CIP`), based on historical data grouped by year and hospital ward. +This approach and idea formed the basis for the publication [DOI: 10.3389/fmicb.2025.1582703](https://doi.org/10.3389/fmicb.2025.1582703) to model the presence of extended-spectrum beta-lactamases (ESBL). + +### **Objective** + +Our goal is to: + +1. Use raw MIC values to predict whether a bacterial isolate produces ESBL. +2. Apply AMR-aware preprocessing in a `tidymodels` recipe. +3. Train a classification model and evaluate its predictive performance. + +### **Data Preparation** + +We use the `esbl_isolates` dataset that comes with the AMR package. + +```{r} +# Load required libraries +library(AMR) +library(tidymodels) + +# View the esbl_isolates data set +esbl_isolates + +# Prepare a binary outcome and convert to ordered factor +data <- esbl_isolates %>% + mutate(esbl = factor(esbl, levels = c(FALSE, TRUE), ordered = TRUE)) +``` + +**Explanation:** + +- `esbl_isolates`: Contains MIC test results and ESBL status for each isolate. +- `mutate(esbl = ...)`: Converts the target column to an ordered factor for classification. + +### **Defining the Workflow** + +#### 1. Preprocessing with a Recipe + +We use our `step_mic_log2()` function to log2-transform MIC values, ensuring that MICs are numeric and properly scaled. All MIC predictors can easily and agnostically selected using the new `all_mic_predictors()`: + +```{r} +# Split into training and testing sets +set.seed(123) +split <- initial_split(data) +training_data <- training(split) +testing_data <- testing(split) + +# Define the recipe +mic_recipe <- recipe(esbl ~ ., data = training_data) %>% + remove_role(genus, old_role = "predictor") %>% # Remove non-informative variable + step_mic_log2(all_mic_predictors()) #%>% # Log2 transform all MIC predictors + # prep() + +mic_recipe +``` + +**Explanation:** + +- `remove_role()`: Removes irrelevant variables like genus. +- `step_mic_log2()`: Applies `log2(as.numeric(...))` to all MIC predictors in one go. +- `prep()`: Finalises the recipe based on training data. + +#### 2. Specifying the Model + +We use a simple logistic regression to model ESBL presence, though recent models such as xgboost ([link to `parsnip` manual](https://parsnip.tidymodels.org/reference/details_boost_tree_xgboost.html)) could be much more precise. + +```{r} +# Define the model +model <- logistic_reg(mode = "classification") %>% + set_engine("glm") + +model +``` + +**Explanation:** + +- `logistic_reg()`: Specifies a binary classification model. +- `set_engine("glm")`: Uses the base R GLM engine. + +#### 3. Building the Workflow + +```{r} +# Create workflow +workflow_model <- workflow() %>% + add_recipe(mic_recipe) %>% + add_model(model) + +workflow_model +``` + +### **Training and Evaluating the Model** + +```{r} +# Fit the model +fitted <- fit(workflow_model, training_data) + +# Generate predictions +predictions <- predict(fitted, testing_data) %>% + bind_cols(testing_data) + +# Evaluate model performance +our_metrics <- metric_set(accuracy, kap, ppv, npv) +metrics <- our_metrics(predictions, truth = esbl, estimate = .pred_class) + +metrics +``` + +**Explanation:** + +- `fit()`: Trains the model on the processed training data. +- `predict()`: Produces predictions for unseen test data. +- `metric_set()`: Allows evaluating multiple classification metrics. + +It appears we can predict ESBL gene presence with a positive predictive value (PPV) of `r round(metrics$.estimate[3], 3) * 100`% and a negative predictive value (NPV) of `r round(metrics$.estimate[4], 3) * 100` using a simplistic logistic regression model. + +### **Visualising Predictions** + +We can visualise predictions by comparing predicted and actual ESBL status. + +```{r} +library(ggplot2) + +ggplot(predictions, aes(x = esbl, fill = .pred_class)) + + geom_bar(position = "stack") + + labs(title = "Predicted vs Actual ESBL Status", + x = "Actual ESBL", + y = "Count") + + theme_minimal() +``` + +### **Conclusion** + +In this example, we showcased how the new `AMR`-specific recipe steps simplify working with `` columns in `tidymodels`. The `step_mic_log2()` transformation converts ordered MICs to log2-transformed numerics, improving compatibility with classification models. + +This pipeline enables realistic, reproducible, and interpretable modelling of antimicrobial resistance data. + +--- + + +## Example 3: Predicting AMR Over Time + +In this third example, we aim to predict antimicrobial resistance (AMR) trends over time using `tidymodels`. We will model resistance to three antibiotics (amoxicillin `AMX`, amoxicillin-clavulanic acid `AMC`, and ciprofloxacin `CIP`), based on historical data grouped by year and hospital ward. ### **Objective** diff --git a/vignettes/welcome_to_AMR.Rmd b/vignettes/welcome_to_AMR.Rmd index 16422f83b..278fc3f27 100644 --- a/vignettes/welcome_to_AMR.Rmd +++ b/vignettes/welcome_to_AMR.Rmd @@ -28,7 +28,7 @@ Note: to keep the package size as small as possible, we only include this vignet The `AMR` package is a peer-reviewed, [free and open-source](https://amr-for-r.org/#copyright) R package with [zero dependencies](https://en.wikipedia.org/wiki/Dependency_hell) to simplify the analysis and prediction of Antimicrobial Resistance (AMR) and to work with microbial and antimicrobial data and properties, by using evidence-based methods. **Our aim is to provide a standard** for clean and reproducible AMR data analysis, that can therefore empower epidemiological analyses to continuously enable surveillance and treatment evaluation in any setting. We are a team of [many different researchers](https://amr-for-r.org/authors.html) from around the globe to make this a successful and durable project! -This work was published in the Journal of Statistical Software (Volume 104(3); \doi{10.18637/jss.v104.i03}) and formed the basis of two PhD theses (\doi{10.33612/diss.177417131} and \doi{10.33612/diss.192486375}). +This work was published in the Journal of Statistical Software (Volume 104(3); [DOI 10.18637/jss.v104.i03](https://doi.org/10.18637/jss.v104.i03)) and formed the basis of two PhD theses ([DOI 10.33612/diss.177417131](https://doi.org/10.33612/diss.177417131) and [DOI 10.33612/diss.192486375](https://doi.org/10.33612/diss.192486375)). After installing this package, R knows [**`r AMR:::format_included_data_number(AMR::microorganisms)` distinct microbial species**](https://amr-for-r.org/reference/microorganisms.html) (updated June 2024) and all [**`r AMR:::format_included_data_number(NROW(AMR::antimicrobials) + NROW(AMR::antivirals))` antimicrobial and antiviral drugs**](https://amr-for-r.org/reference/antimicrobials.html) by name and code (including ATC, EARS-Net, ASIARS-Net, PubChem, LOINC and SNOMED CT), and knows all about valid SIR and MIC values. The integral clinical breakpoint guidelines from CLSI `r min(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, grepl("CLSI", guideline))$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, grepl("CLSI", guideline))$guideline)))` and EUCAST `r min(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, grepl("EUCAST", guideline))$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, grepl("EUCAST", guideline))$guideline)))` are included, even with epidemiological cut-off (ECOFF) values. It supports and can read any data format, including WHONET data. This package works on Windows, macOS and Linux with all versions of R since R-3.0 (April 2013). **It was designed to work in any setting, including those with very limited resources**. It was created for both routine data analysis and academic research at the Faculty of Medical Sciences of the [University of Groningen](https://www.rug.nl) and the [University Medical Center Groningen](https://www.umcg.nl).