mirror of
https://github.com/msberends/AMR.git
synced 2026-03-11 15:47:54 +01:00
(v3.0.1.9031) fix MDRO for non-RStudio terminal
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
Package: AMR
|
Package: AMR
|
||||||
Version: 3.0.1.9030
|
Version: 3.0.1.9031
|
||||||
Date: 2026-03-07
|
Date: 2026-03-08
|
||||||
Title: Antimicrobial Resistance Data Analysis
|
Title: Antimicrobial Resistance Data Analysis
|
||||||
Description: Functions to simplify and standardise antimicrobial resistance (AMR)
|
Description: Functions to simplify and standardise antimicrobial resistance (AMR)
|
||||||
data analysis and to work with microbial and antimicrobial properties by
|
data analysis and to work with microbial and antimicrobial properties by
|
||||||
|
|||||||
4
NEWS.md
4
NEWS.md
@@ -1,4 +1,4 @@
|
|||||||
# AMR 3.0.1.9030
|
# AMR 3.0.1.9031
|
||||||
|
|
||||||
### New
|
### New
|
||||||
* Integration with the **tidymodels** framework to allow seamless use of SIR, MIC and disk data in modelling pipelines via `recipes`
|
* Integration with the **tidymodels** framework to allow seamless use of SIR, MIC and disk data in modelling pipelines via `recipes`
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
* Two new `NA` objects, `NA_ab_` and `NA_mo_`, analogous to base R's `NA_character_` and `NA_integer_`, for use in pipelines that require typed missing values
|
* Two new `NA` objects, `NA_ab_` and `NA_mo_`, analogous to base R's `NA_character_` and `NA_integer_`, for use in pipelines that require typed missing values
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
* `mdro()`: when a base beta-lactam drug column is missing but a corresponding drug+inhibitor combination is present in the data and resistant (e.g., piperacillin/tazobactam = R while piperacillin is absent), the base drug is now correctly inferred as resistant. This ensures MDRO classification is not missed due to test-ordering differences in the laboratory. The reverse direction is also valid: susceptibility in a combination does not imply susceptibility in the base drug (the inhibitor may be responsible), so only resistance is propagated. Closes #209
|
|
||||||
* Fixed a bug in `as.sir()` where values that were purely numeric (e.g., `"1"`) and matched the broad SIR-matching regex would be incorrectly stripped of all content by the Unicode letter filter
|
* Fixed a bug in `as.sir()` where values that were purely numeric (e.g., `"1"`) and matched the broad SIR-matching regex would be incorrectly stripped of all content by the Unicode letter filter
|
||||||
* Fixed a bug in `as.mic()` where MIC values in scientific notation (e.g., `"1e-3"`) were incorrectly handled because the letter `e` was removed along with other Unicode letters; scientific notation `e` is now preserved
|
* Fixed a bug in `as.mic()` where MIC values in scientific notation (e.g., `"1e-3"`) were incorrectly handled because the letter `e` was removed along with other Unicode letters; scientific notation `e` is now preserved
|
||||||
* Fixed a bug in `as.ab()` where certain AB codes containing "PH" or "TH" (such as `ETH`, `MTH`, `PHE`, `PHN`, `STH`, `THA`, `THI1`) would incorrectly return `NA` when combined in a vector with any untranslatable value (#245)
|
* Fixed a bug in `as.ab()` where certain AB codes containing "PH" or "TH" (such as `ETH`, `MTH`, `PHE`, `PHN`, `STH`, `THA`, `THI1`) would incorrectly return `NA` when combined in a vector with any untranslatable value (#245)
|
||||||
@@ -31,6 +30,7 @@
|
|||||||
* Fixed SIR and MIC coercion of combined values, e.g. `as.sir("<= 0.002; S") ` or `as.mic("S; 0.002")` (#252)
|
* Fixed SIR and MIC coercion of combined values, e.g. `as.sir("<= 0.002; S") ` or `as.mic("S; 0.002")` (#252)
|
||||||
|
|
||||||
### Updates
|
### Updates
|
||||||
|
* `mdro()` now infers resistance for a _missing_ base drug column from an _available_ corresponding drug+inhibitor combination showing resistance (e.g., piperacillin is absent but required, while piperacillin/tazobactam available and resistant). Can be set with the new argument `infer_from_combinations`, which defaults to `TRUE` (#209). Note that this can yield a higher MDRO detection (which is a good thing as it has become more reliable).
|
||||||
* `susceptibility()` and `resistance()` gained the argument `guideline`, which defaults to EUCAST, for interpreting the 'I' category correctly.
|
* `susceptibility()` and `resistance()` gained the argument `guideline`, which defaults to EUCAST, for interpreting the 'I' category correctly.
|
||||||
* `as.mic()` and `rescale_mic()` gained the argument `round_to_next_log2`, which can be set to `TRUE` to round all values up to the nearest next log2 level (#255)
|
* `as.mic()` and `rescale_mic()` gained the argument `round_to_next_log2`, which can be set to `TRUE` to round all values up to the nearest next log2 level (#255)
|
||||||
* `antimicrobials$group` is now a `list` instead of a `character`, to contain any group the drug is in (#246)
|
* `antimicrobials$group` is now a `list` instead of a `character`, to contain any group the drug is in (#246)
|
||||||
|
|||||||
@@ -387,6 +387,10 @@ import_fn <- function(name, pkg, error_on_fail = TRUE) {
|
|||||||
if (isTRUE(error_on_fail)) {
|
if (isTRUE(error_on_fail)) {
|
||||||
stop_ifnot_installed(pkg)
|
stop_ifnot_installed(pkg)
|
||||||
}
|
}
|
||||||
|
if (pkg == "rstudioapi" && tryCatch(!rstudioapi::isAvailable(), error = function(e) TRUE)) {
|
||||||
|
# only allow rstudioapi to be imported if RStudio is available
|
||||||
|
return(NULL)
|
||||||
|
}
|
||||||
tryCatch(
|
tryCatch(
|
||||||
# don't use get() to avoid fetching non-API functions
|
# don't use get() to avoid fetching non-API functions
|
||||||
getExportedValue(name = name, ns = asNamespace(pkg)),
|
getExportedValue(name = name, ns = asNamespace(pkg)),
|
||||||
@@ -1220,10 +1224,14 @@ try_colour <- function(..., before, after, collapse = " ") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is_dark <- function() {
|
is_dark <- function() {
|
||||||
AMR_env$current_theme <- tryCatch(getExportedValue("getThemeInfo", ns = asNamespace("rstudioapi"))()$editor, error = function(e) NULL)
|
AMR_env$current_theme <- NULL
|
||||||
|
current_theme_fn <- import_fn("getThemeInfo", "rstudioapi", error_on_fail = FALSE)
|
||||||
|
if (!is.null(current_theme_fn)) {
|
||||||
|
AMR_env$current_theme <- current_theme_fn()$editor
|
||||||
|
}
|
||||||
if (!identical(AMR_env$current_theme, AMR_env$former_theme) || is.null(AMR_env$is_dark_theme)) {
|
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$former_theme <- AMR_env$current_theme
|
||||||
AMR_env$is_dark_theme <- !has_colour() || tryCatch(isTRUE(getExportedValue("getThemeInfo", ns = asNamespace("rstudioapi"))()$dark), error = function(e) TRUE)
|
AMR_env$is_dark_theme <- !has_colour() || tryCatch(isTRUE(current_theme_fn()$dark), error = function(e) TRUE)
|
||||||
}
|
}
|
||||||
isTRUE(AMR_env$is_dark_theme)
|
isTRUE(AMR_env$is_dark_theme)
|
||||||
}
|
}
|
||||||
|
|||||||
85
R/mdro.R
85
R/mdro.R
@@ -31,7 +31,7 @@
|
|||||||
#'
|
#'
|
||||||
#' Determine which isolates are multidrug-resistant organisms (MDRO) according to international, national, or custom guidelines.
|
#' Determine which isolates are multidrug-resistant organisms (MDRO) according to international, national, or custom guidelines.
|
||||||
#' @param x A [data.frame] with antimicrobials columns, like `AMX` or `amox`. Can be left blank for automatic determination.
|
#' @param x A [data.frame] with antimicrobials columns, like `AMX` or `amox`. Can be left blank for automatic determination.
|
||||||
#' @param guideline A specific guideline to follow, see sections *Supported international / national guidelines* and *Using Custom Guidelines* below. When left empty, the publication by Magiorakos *et al.* (see below) will be followed.
|
#' @param guideline A specific guideline to follow, see sections *Supported International / National Guidelines* and *Using Custom Guidelines* below. When left empty, the publication by Magiorakos *et al.* (see below) will be followed.
|
||||||
#' @param esbl [logical] values, or a column name containing logical values, indicating the presence of an ESBL gene (or production of its proteins).
|
#' @param esbl [logical] values, or a column name containing logical values, indicating the presence of an ESBL gene (or production of its proteins).
|
||||||
#' @param carbapenemase [logical] values, or a column name containing logical values, indicating the presence of a carbapenemase gene (or production of its proteins).
|
#' @param carbapenemase [logical] values, or a column name containing logical values, indicating the presence of a carbapenemase gene (or production of its proteins).
|
||||||
#' @param mecA [logical] values, or a column name containing logical values, indicating the presence of a *mecA* gene (or production of its proteins).
|
#' @param mecA [logical] values, or a column name containing logical values, indicating the presence of a *mecA* gene (or production of its proteins).
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
#' @param pct_required_classes Minimal required percentage of antimicrobial classes that must be available per isolate, rounded down. For example, with the default guideline, 17 antimicrobial classes must be available for *S. aureus*. Setting this `pct_required_classes` argument to `0.5` (default) means that for every *S. aureus* isolate at least 8 different classes must be available. Any lower number of available classes will return `NA` for that isolate.
|
#' @param pct_required_classes Minimal required percentage of antimicrobial classes that must be available per isolate, rounded down. For example, with the default guideline, 17 antimicrobial classes must be available for *S. aureus*. Setting this `pct_required_classes` argument to `0.5` (default) means that for every *S. aureus* isolate at least 8 different classes must be available. Any lower number of available classes will return `NA` for that isolate.
|
||||||
#' @param combine_SI A [logical] to indicate whether all values of S and I must be merged into one, so resistance is only considered when isolates are R, not I. As this is the default behaviour of the [mdro()] function, it follows the redefinition by EUCAST about the interpretation of I (increased exposure) in 2019, see section 'Interpretation of S, I and R' below. When using `combine_SI = FALSE`, resistance is considered when isolates are R or I.
|
#' @param combine_SI A [logical] to indicate whether all values of S and I must be merged into one, so resistance is only considered when isolates are R, not I. As this is the default behaviour of the [mdro()] function, it follows the redefinition by EUCAST about the interpretation of I (increased exposure) in 2019, see section 'Interpretation of S, I and R' below. When using `combine_SI = FALSE`, resistance is considered when isolates are R or I.
|
||||||
#' @param verbose A [logical] to turn Verbose mode on and off (default is off). In Verbose mode, the function returns a data set with the MDRO results in logbook form with extensive info about which isolates would be MDRO-positive, or why they are not.
|
#' @param verbose A [logical] to turn Verbose mode on and off (default is off). In Verbose mode, the function returns a data set with the MDRO results in logbook form with extensive info about which isolates would be MDRO-positive, or why they are not.
|
||||||
|
#' @param infer_from_combinations A [logical] to indicate whether resistance for a missing base beta-lactam drug should be inferred from an available drug+inhibitor combination (e.g., piperacillin from piperacillin/tazobactam). The clinical basis is that resistance in a combination always implies resistance in the base drug, since the enzyme inhibitor provides no benefit when the organism is truly resistant. Only resistance is inferred; susceptibility in a combination does **not** imply susceptibility in the base drug (the inhibitor may be responsible). Defaults to `TRUE`.
|
||||||
#' @details
|
#' @details
|
||||||
#' These functions are context-aware. This means that the `x` argument can be left blank if used inside a [data.frame] call, see *Examples*.
|
#' These functions are context-aware. This means that the `x` argument can be left blank if used inside a [data.frame] call, see *Examples*.
|
||||||
#'
|
#'
|
||||||
@@ -143,6 +144,7 @@ mdro <- function(x = NULL,
|
|||||||
combine_SI = TRUE,
|
combine_SI = TRUE,
|
||||||
verbose = FALSE,
|
verbose = FALSE,
|
||||||
only_sir_columns = any(is.sir(x)),
|
only_sir_columns = any(is.sir(x)),
|
||||||
|
infer_from_combinations = TRUE,
|
||||||
...) {
|
...) {
|
||||||
if (is_null_or_grouped_tbl(x)) {
|
if (is_null_or_grouped_tbl(x)) {
|
||||||
# when `x` is left blank, auto determine it (get_current_data() searches underlying data within call)
|
# when `x` is left blank, auto determine it (get_current_data() searches underlying data within call)
|
||||||
@@ -165,7 +167,7 @@ mdro <- function(x = NULL,
|
|||||||
meet_criteria(combine_SI, allow_class = "logical", has_length = 1)
|
meet_criteria(combine_SI, allow_class = "logical", has_length = 1)
|
||||||
meet_criteria(verbose, allow_class = "logical", has_length = 1)
|
meet_criteria(verbose, allow_class = "logical", has_length = 1)
|
||||||
meet_criteria(only_sir_columns, allow_class = "logical", has_length = 1)
|
meet_criteria(only_sir_columns, allow_class = "logical", has_length = 1)
|
||||||
|
meet_criteria(infer_from_combinations, allow_class = "logical", has_length = 1)
|
||||||
|
|
||||||
if (isTRUE(only_sir_columns) && !any(is.sir(x))) {
|
if (isTRUE(only_sir_columns) && !any(is.sir(x))) {
|
||||||
stop_("There were no SIR columns found in the data set, despite `only_sir_columns` being `TRUE`. Transform columns with `as.sir()` for valid antimicrobial interpretations.")
|
stop_("There were no SIR columns found in the data set, despite `only_sir_columns` being `TRUE`. Transform columns with `as.sir()` for valid antimicrobial interpretations.")
|
||||||
@@ -480,49 +482,51 @@ mdro <- function(x = NULL,
|
|||||||
}
|
}
|
||||||
cols_ab <- cols_ab[!duplicated(cols_ab)]
|
cols_ab <- cols_ab[!duplicated(cols_ab)]
|
||||||
|
|
||||||
# Infer resistance for missing base drugs from available drug+inhibitor combination columns.
|
# Infer resistance for missing base drugs ----
|
||||||
# Clinical principle: resistance in drug+inhibitor (e.g., piperacillin/tazobactam = R)
|
if (isTRUE(infer_from_combinations)) {
|
||||||
# always implies resistance in the base drug (e.g., piperacillin = R), because the
|
.combos_in_data <- AB_BETALACTAMS_WITH_INHIBITOR[AB_BETALACTAMS_WITH_INHIBITOR %in% names(cols_ab)]
|
||||||
# enzyme inhibitor adds nothing when the organism is truly resistant to the base drug.
|
if (length(.combos_in_data) > 0) {
|
||||||
# NOTE: susceptibility in a combination does NOT imply susceptibility in the base drug
|
.base_drugs <- suppressMessages(
|
||||||
# (the inhibitor may be responsible), so synthetic proxy columns only propagate R, not S/I.
|
as.ab(gsub("/.*", "", ab_name(as.character(.combos_in_data), language = NULL)))
|
||||||
.combos_in_data <- AB_BETALACTAMS_WITH_INHIBITOR[AB_BETALACTAMS_WITH_INHIBITOR %in% names(cols_ab)]
|
)
|
||||||
if (length(.combos_in_data) > 0) {
|
.unique_bases <- unique(.base_drugs[!is.na(.base_drugs)])
|
||||||
.base_drugs <- suppressMessages(
|
for (.base in .unique_bases) {
|
||||||
as.ab(gsub("/.*", "", ab_name(as.character(.combos_in_data), language = NULL)))
|
.base_code <- as.character(.base)
|
||||||
)
|
if (!.base_code %in% names(cols_ab)) {
|
||||||
.unique_bases <- unique(.base_drugs[!is.na(.base_drugs)])
|
# Base drug column absent; find all available combo columns for this base drug
|
||||||
for (.base in .unique_bases) {
|
.combos <- .combos_in_data[!is.na(.base_drugs) & as.character(.base_drugs) == .base_code]
|
||||||
.base_code <- as.character(.base)
|
.combo_cols <- unname(cols_ab[as.character(.combos)])
|
||||||
if (!.base_code %in% names(cols_ab)) {
|
.combo_cols <- .combo_cols[!is.na(.combo_cols)]
|
||||||
# Base drug column absent; find all available combo columns for this base drug
|
if (length(.combo_cols) > 0) {
|
||||||
.combos <- .combos_in_data[!is.na(.base_drugs) & as.character(.base_drugs) == .base_code]
|
# Vectorised: if ANY combination is R, infer base drug as R; otherwise NA
|
||||||
.combo_cols <- unname(cols_ab[as.character(.combos)])
|
.sir_chars <- as.data.frame(
|
||||||
.combo_cols <- .combo_cols[!is.na(.combo_cols)]
|
lapply(x[, .combo_cols, drop = FALSE], function(col) as.character(as.sir(col))),
|
||||||
if (length(.combo_cols) > 0) {
|
stringsAsFactors = FALSE
|
||||||
# Vectorised: if ANY combination is R, infer base drug as R; otherwise NA
|
|
||||||
.sir_chars <- as.data.frame(
|
|
||||||
lapply(x[, .combo_cols, drop = FALSE], function(col) as.character(as.sir(col))),
|
|
||||||
stringsAsFactors = FALSE
|
|
||||||
)
|
|
||||||
.new_col <- paste0(".sir_proxy_", .base_code)
|
|
||||||
x[[.new_col]] <- ifelse(rowSums(.sir_chars == "R", na.rm = TRUE) > 0L, "R", NA_character_)
|
|
||||||
cols_ab <- c(cols_ab, stats::setNames(.new_col, .base_code))
|
|
||||||
if (isTRUE(verbose)) {
|
|
||||||
message_(
|
|
||||||
"Inferring resistance for ", ab_name(.base_code, language = NULL),
|
|
||||||
" from available drug+inhibitor combination(s): ",
|
|
||||||
paste(ab_name(as.character(.combos), language = NULL), collapse = ", "),
|
|
||||||
" (resistance in a combination always implies resistance in the base drug)",
|
|
||||||
add_fn = font_blue
|
|
||||||
)
|
)
|
||||||
|
.new_col <- paste0(.base_code, ".inferred_sir_proxy_from#", paste0(.combos, collapse = "/"), "#")
|
||||||
|
x[[.new_col]] <- ifelse(rowSums(.sir_chars == "R", na.rm = TRUE) > 0L, "R", NA_character_)
|
||||||
|
cols_ab <- c(cols_ab, stats::setNames(.new_col, .base_code))
|
||||||
|
if (info == TRUE) {
|
||||||
|
message_(
|
||||||
|
"Inferring resistance for ",
|
||||||
|
ab_name(.base_code, language = NULL, tolower = TRUE),
|
||||||
|
" (", font_bold(.base_code, collapse = NULL), ", ", font_italic("missing"), ") from ",
|
||||||
|
vector_or(
|
||||||
|
quotes = FALSE,
|
||||||
|
last_sep = " and/or ",
|
||||||
|
paste0(
|
||||||
|
ab_name(.combos, language = NULL, tolower = TRUE),
|
||||||
|
" (", font_bold(.combos, collapse = NULL), ", ", font_italic("available"), ")"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cols_ab <- cols_ab[!duplicated(names(cols_ab))]
|
||||||
}
|
}
|
||||||
cols_ab <- cols_ab[!duplicated(names(cols_ab))]
|
|
||||||
}
|
}
|
||||||
rm(list = intersect(ls(), c(".combos_in_data", ".base_drugs", ".unique_bases", ".base", ".base_code", ".combos", ".combo_cols", ".sir_chars", ".new_col")))
|
|
||||||
|
|
||||||
# nolint start
|
# nolint start
|
||||||
AMC <- cols_ab["AMC"]
|
AMC <- cols_ab["AMC"]
|
||||||
@@ -1937,7 +1941,8 @@ mdro <- function(x = NULL,
|
|||||||
# format data set
|
# format data set
|
||||||
colnames(x)[colnames(x) == col_mo] <- "microorganism"
|
colnames(x)[colnames(x) == col_mo] <- "microorganism"
|
||||||
x$microorganism <- mo_name(x$microorganism, language = NULL)
|
x$microorganism <- mo_name(x$microorganism, language = NULL)
|
||||||
x$guideline <- paste0(guideline$author, " - ", guideline$name, ", ", guideline$version, ")")
|
x$guideline <- paste0(guideline$author, " - ", guideline$name, ifelse(is.na(guideline$version), "", paste0(" (", guideline$version, ")")))
|
||||||
|
x$all_nonsusceptible_columns <- gsub(".inferred_sir_proxy_from#(.*?)#", " (inferred from \\1)", x$all_nonsusceptible_columns, perl = TRUE)
|
||||||
x[, c(
|
x[, c(
|
||||||
"row_number",
|
"row_number",
|
||||||
"microorganism",
|
"microorganism",
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
mdro(x = NULL, guideline = "CMI 2012", col_mo = NULL, esbl = NA,
|
mdro(x = NULL, guideline = "CMI 2012", col_mo = NULL, esbl = NA,
|
||||||
carbapenemase = NA, mecA = NA, mecC = NA, vanA = NA, vanB = NA,
|
carbapenemase = NA, mecA = NA, mecC = NA, vanA = NA, vanB = NA,
|
||||||
info = interactive(), pct_required_classes = 0.5, combine_SI = TRUE,
|
info = interactive(), pct_required_classes = 0.5, combine_SI = TRUE,
|
||||||
verbose = FALSE, only_sir_columns = any(is.sir(x)), ...)
|
verbose = FALSE, only_sir_columns = any(is.sir(x)),
|
||||||
|
infer_from_combinations = TRUE, ...)
|
||||||
|
|
||||||
brmo(x = NULL, only_sir_columns = any(is.sir(x)), ...)
|
brmo(x = NULL, only_sir_columns = any(is.sir(x)), ...)
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ eucast_exceptional_phenotypes(x = NULL, only_sir_columns = any(is.sir(x)),
|
|||||||
\arguments{
|
\arguments{
|
||||||
\item{x}{A \link{data.frame} with antimicrobials columns, like \code{AMX} or \code{amox}. Can be left blank for automatic determination.}
|
\item{x}{A \link{data.frame} with antimicrobials columns, like \code{AMX} or \code{amox}. Can be left blank for automatic determination.}
|
||||||
|
|
||||||
\item{guideline}{A specific guideline to follow, see sections \emph{Supported international / national guidelines} and \emph{Using Custom Guidelines} below. When left empty, the publication by Magiorakos \emph{et al.} (see below) will be followed.}
|
\item{guideline}{A specific guideline to follow, see sections \emph{Supported International / National Guidelines} and \emph{Using Custom Guidelines} below. When left empty, the publication by Magiorakos \emph{et al.} (see below) will be followed.}
|
||||||
|
|
||||||
\item{col_mo}{Column name of the names or codes of the microorganisms (see \code{\link[=as.mo]{as.mo()}}) - the default is the first column of class \code{\link{mo}}. Values will be coerced using \code{\link[=as.mo]{as.mo()}}.}
|
\item{col_mo}{Column name of the names or codes of the microorganisms (see \code{\link[=as.mo]{as.mo()}}) - the default is the first column of class \code{\link{mo}}. Values will be coerced using \code{\link[=as.mo]{as.mo()}}.}
|
||||||
|
|
||||||
@@ -61,6 +62,8 @@ eucast_exceptional_phenotypes(x = NULL, only_sir_columns = any(is.sir(x)),
|
|||||||
|
|
||||||
\item{only_sir_columns}{A \link{logical} to indicate whether only antimicrobial columns must be included that were transformed to class \link[=as.sir]{sir} on beforehand. Defaults to \code{FALSE} if no columns of \code{x} have a class \link[=as.sir]{sir}.}
|
\item{only_sir_columns}{A \link{logical} to indicate whether only antimicrobial columns must be included that were transformed to class \link[=as.sir]{sir} on beforehand. Defaults to \code{FALSE} if no columns of \code{x} have a class \link[=as.sir]{sir}.}
|
||||||
|
|
||||||
|
\item{infer_from_combinations}{A \link{logical} to indicate whether resistance for a missing base beta-lactam drug should be inferred from an available drug+inhibitor combination (e.g., piperacillin from piperacillin/tazobactam). The clinical basis is that resistance in a combination always implies resistance in the base drug, since the enzyme inhibitor provides no benefit when the organism is truly resistant. Only resistance is inferred; susceptibility in a combination does \strong{not} imply susceptibility in the base drug (the inhibitor may be responsible). Defaults to \code{TRUE}.}
|
||||||
|
|
||||||
\item{...}{Column names of antimicrobials. To automatically detect antimicrobial column names, do not provide any named arguments; \code{\link[=guess_ab_col]{guess_ab_col()}} will then be used for detection. To manually specify a column, provide its name (case-insensitive) as an argument, e.g. \code{AMX = "amoxicillin"}. To skip a specific antimicrobial, set it to \code{NULL}, e.g. \code{TIC = NULL} to exclude ticarcillin. If a manually defined column does not exist in the data, it will be skipped with a warning.}
|
\item{...}{Column names of antimicrobials. To automatically detect antimicrobial column names, do not provide any named arguments; \code{\link[=guess_ab_col]{guess_ab_col()}} will then be used for detection. To manually specify a column, provide its name (case-insensitive) as an argument, e.g. \code{AMX = "amoxicillin"}. To skip a specific antimicrobial, set it to \code{NULL}, e.g. \code{TIC = NULL} to exclude ticarcillin. If a manually defined column does not exist in the data, it will be skipped with a warning.}
|
||||||
}
|
}
|
||||||
\value{
|
\value{
|
||||||
|
|||||||
@@ -313,14 +313,14 @@ test_that("test-mdro.R", {
|
|||||||
# Inference message goes to message() / stderr, not stdout
|
# Inference message goes to message() / stderr, not stdout
|
||||||
# -> must use expect_message(), NOT expect_output()
|
# -> must use expect_message(), NOT expect_output()
|
||||||
expect_message(
|
expect_message(
|
||||||
suppressWarnings(mdro(pseud_no_pip, guideline = "mrgn", info = FALSE, verbose = TRUE)),
|
suppressWarnings(mdro(pseud_no_pip, guideline = "mrgn", info = TRUE)),
|
||||||
"Inferring resistance"
|
"Inferring resistance"
|
||||||
)
|
)
|
||||||
# With TZP=R, PIP is inferred R -> 4MRGN criteria met -> level 3 (> 1)
|
inferred <- suppressWarnings(mdro(pseud_no_pip, guideline = "mrgn", info = FALSE))
|
||||||
result_no_pip <- suppressMessages(suppressWarnings(
|
not_inferred <- suppressWarnings(mdro(pseud_no_pip, guideline = "mrgn", info = FALSE, infer_from_combinations = FALSE))
|
||||||
mdro(pseud_no_pip, guideline = "mrgn", info = FALSE)
|
expect_equal(as.character(inferred), "4MRGN")
|
||||||
))
|
expect_equal(as.character(not_inferred), "Negative")
|
||||||
expect_true(as.integer(result_no_pip) > 1L)
|
|
||||||
# Susceptibility in combo does NOT propagate: proxy = NA, not S
|
# Susceptibility in combo does NOT propagate: proxy = NA, not S
|
||||||
# -> 4MRGN criteria no longer met -> lower level than when TZP=R
|
# -> 4MRGN criteria no longer met -> lower level than when TZP=R
|
||||||
pseud_tzp_s <- pseud_no_pip
|
pseud_tzp_s <- pseud_no_pip
|
||||||
@@ -328,18 +328,23 @@ test_that("test-mdro.R", {
|
|||||||
result_tzp_s <- suppressMessages(suppressWarnings(
|
result_tzp_s <- suppressMessages(suppressWarnings(
|
||||||
mdro(pseud_tzp_s, guideline = "mrgn", info = FALSE)
|
mdro(pseud_tzp_s, guideline = "mrgn", info = FALSE)
|
||||||
))
|
))
|
||||||
expect_true(as.integer(result_tzp_s) < as.integer(result_no_pip))
|
expect_true(as.integer(result_tzp_s) < as.integer(inferred))
|
||||||
|
|
||||||
# Multiple combos for the same base drug: AMX can come from AMC (amoxicillin/clavulanic acid)
|
# Multiple combos for the same base drug: AMX can come from AMC (amoxi/clavulanic acid) and AXS (amoxi/sulbactam)
|
||||||
ente_no_amx <- data.frame(
|
ente_no_amx <- data.frame(
|
||||||
mo = as.mo("Enterococcus faecium"),
|
mo = as.mo("Enterococcus faecium"),
|
||||||
AMC = as.sir("R"), # amoxicillin/clavulanic acid; no AMX column
|
AMC = as.sir("R"), # amoxicillin/clavulanic acid
|
||||||
|
AXS = as.sir("R"), # amoxicillin/sulbactam
|
||||||
VAN = as.sir("R"),
|
VAN = as.sir("R"),
|
||||||
TEC = as.sir("R"),
|
TEC = as.sir("R"),
|
||||||
LNZ = as.sir("R"),
|
LNZ = as.sir("R"),
|
||||||
DAP = as.sir("R"),
|
DAP = as.sir("R"),
|
||||||
stringsAsFactors = FALSE
|
stringsAsFactors = FALSE
|
||||||
)
|
)
|
||||||
# Should run without error and return an ordered factor; AMX inferred R from AMC
|
# Should have multiple columns in the verbose explanation
|
||||||
expect_inherits(suppressMessages(suppressWarnings(mdro(ente_no_amx, guideline = "EUCAST", info = FALSE))), c("factor", "ordered"))
|
out <- mdro(ente_no_amx, guideline = "EUCAST 3.3", info = FALSE, verbose = TRUE)
|
||||||
|
expect_identical(
|
||||||
|
out$all_nonsusceptible_columns,
|
||||||
|
"AMC, AMX (inferred from AMC/AXS), AXS, DAP, LNZ, TEC, VAN"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user