mirror of
https://github.com/msberends/AMR.git
synced 2026-11-16 00:10:57 +01:00
(v3.0.1.9115) Fix interpretation of capped MICs without an S category (off-scale S breakpoint) or without breakpoints in as.sir(), and correct the documented default of capped_mic_handling (#295)
This commit is contained in:
1 parent
9e609dae83
commit
80afedeb8c
7 files changed
+113
-37
No files matched your search
+2
-2
@@ -1,6 +1,6 @@
|
||||
Package: AMR
|
||||
Version: 3.0.1.9114
|
||||
Date: 2026-10-10
|
||||
Version: 3.0.1.9115
|
||||
Date: 2026-10-11
|
||||
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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# AMR 3.0.1.9114
|
||||
# AMR 3.0.1.9115
|
||||
|
||||
Planned as v3.1.0, mid October 2026.
|
||||
|
||||
@@ -57,6 +57,9 @@ Planned as v3.1.0, mid October 2026.
|
||||
* Metadata columns (e.g. `patient`, `ward`) no longer misidentified as antibiotic columns
|
||||
* `info = FALSE` now suppresses all messages, including for columns without breakpoints
|
||||
* Assumption of disk zones are now preferred over MIC values when input is only whole numbers (#291)
|
||||
* Capped MICs (e.g. `<=0.5`) are now `I` instead of `S` or `NI` if there is no S category, i.e. an off-scale S breakpoint such as EUCAST's 0.001 mg/L (#295)
|
||||
* Capped MICs are no longer forced to `S` or `R` if there is no breakpoint for the drug-bug combination
|
||||
* Documented default of `capped_mic_handling` corrected to `"standard"`
|
||||
* `as.mic()`: values in scientific notation (e.g. `1e-3`) now handled correctly
|
||||
* `as.ab()`: codes containing "PH" or "TH" (e.g. `ETH`, `PHE`) no longer return `NA` when mixed with unrecognised input (#245)
|
||||
* `as.ab()`: results of `fast_mode` (used internally) were remembered and reused by later regular calls, which could return `NA` for valid input (#313)
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@
|
||||
#' @section Options (alphabetical order):
|
||||
#' * `AMR_antibiogram_formatting_type` \cr A [numeric] (1-22) to use in [antibiogram()], to indicate which formatting type to use.
|
||||
#' * `AMR_breakpoint_type` \cr A [character] to use in [as.sir()], to indicate which breakpoint type to use. This must be either `r vector_or(clinical_breakpoints$type, documentation = TRUE)`.
|
||||
#' * `AMR_capped_mic_handling` \cr A [character] to use in [as.sir()], to indicate how capped MIC values (`<`, `<=`, `>`, `>=`) should be interpreted. Must be one of `"none"`, `"conservative"`, `"standard"`, or `"lenient"` - the default is `"conservative"`.
|
||||
#' * `AMR_capped_mic_handling` \cr A [character] to use in [as.sir()], to indicate how capped MIC values (`<`, `<=`, `>`, `>=`) should be interpreted. Must be one of `"none"`, `"conservative"`, `"standard"`, or `"lenient"` - the default is `"standard"`.
|
||||
#' * `AMR_cleaning_regex` \cr A [regular expression][base::regex] (case-insensitive) to use in [as.mo()] and all [`mo_*`][mo_property()] functions, to clean the user input. The default is the outcome of [mo_cleaning_regex()], which removes texts between brackets and texts such as "species" and "serovar".
|
||||
#' * `AMR_custom_ab` \cr A file location to an RDS file, to use custom antimicrobial drugs with this package. This is explained in [add_custom_antimicrobials()].
|
||||
#' * `AMR_custom_mo` \cr A file location to an RDS file, to use custom microorganisms with this package. This is explained in [add_custom_microorganisms()].
|
||||
|
||||
@@ -46,11 +46,11 @@ VALID_SIR_LEVELS <- c("S", "SDD", "I", "R", "NI", "WT", "NWT", "NS")
|
||||
#' `"none"`
|
||||
#' * `<=`, `<`, `>` and `>=` are ignored.
|
||||
#'
|
||||
#' `"conservative"` (default)
|
||||
#' `"conservative"`
|
||||
#' * `<=`, `<`, `>` and `>=` return `"NI"` (non-interpretable) if the *true* MIC could be at either side of the breakpoint.
|
||||
#' * This is the only mode that preserves uncertainty for ECOFFs.
|
||||
#'
|
||||
#' `"standard"`
|
||||
#' `"standard"` (default)
|
||||
#' * `<=` and `>=` return `"NI"` (non-interpretable) if the *true* MIC could be at either side of the breakpoint.
|
||||
#' * `<` always returns `"S"`, regardless of the breakpoint.
|
||||
#' * `>` always returns `"R"`, regardless of the breakpoint.
|
||||
@@ -59,7 +59,9 @@ VALID_SIR_LEVELS <- c("S", "SDD", "I", "R", "NI", "WT", "NWT", "NS")
|
||||
#' * `<=` and `<` always return `"S"`, regardless of the breakpoint.
|
||||
#' * `>=` and `>` always return `"R"`, regardless of the breakpoint.
|
||||
#'
|
||||
#' The default `"conservative"` setting ensures cautious handling of uncertain values while preserving interpretability. This option can also be set with the package option [`AMR_capped_mic_handling`][AMR-options].
|
||||
#' In all modes except `"none"`, a capped value is never forced to a category that the guideline does not provide for the drug-bug combination: if a breakpoint is missing, the result is `NA` as for uncapped values. EUCAST uses an off-scale S breakpoint of 0.001 mg/L to indicate that there is no S category (stored as 0.0001 in [clinical_breakpoints]; any S breakpoint of 0.001 or lower is treated as such). In that case, `<` and `<=` values that cannot be `"R"` return `"I"` (or `"SDD"`), and `"standard"` and `"lenient"` return `"I"` (or `"SDD"`) instead of `"S"`.
|
||||
#'
|
||||
#' The default `"standard"` setting ensures cautious handling of uncertain values while preserving interpretability. This option can also be set with the package option [`AMR_capped_mic_handling`][AMR-options].
|
||||
#' @param as_wt_nwt A [logical] to return `"WT"`/`"NWT"` instead of `"S"`/`"R"`. Defaults to `TRUE` when using ECOFFs, i.e., when `breakpoint_type` is set to `"ECOFF"`.
|
||||
#' @param add_intrinsic_resistance *(only useful when using a EUCAST guideline)* a [logical] to indicate whether intrinsic antibiotic resistance must also be considered for applicable bug-drug combinations, meaning that e.g. ampicillin will always return "R" in *Klebsiella* species. Determination is based on the [intrinsic_resistant] data set, that itself is based on `r format_eucast_version_nr(3.3)`.
|
||||
#' @param substitute_missing_r_breakpoint A [logical] to indicate that a missing clinical breakpoints for R (resistant) must be substituted with R - the default is `FALSE`. Some (especially CLSI) breakpoints only have a breakpoint for S, meaning that the outcome can only be `"S"` or `NA`. Setting this to `TRUE` will convert the `NA`s in these cases to `"R"`. Can also be set with the package option [`AMR_substitute_missing_r_breakpoint`][AMR-options].
|
||||
@@ -99,7 +101,7 @@ VALID_SIR_LEVELS <- c("S", "SDD", "I", "R", "NI", "WT", "NWT", "NS")
|
||||
#' # fast processing with parallel computing (requires future.apply):
|
||||
#' as.sir(your_data, ..., parallel = TRUE)
|
||||
#' ```
|
||||
#' * Operators like "<=" will be considered according to the `capped_mic_handling` setting. At default, an MIC value of e.g. ">2" will return "NI" (non-interpretable) if the breakpoint is 4-8; the *true* MIC could be at either side of the breakpoint. This is to prevent that capped values from raw laboratory data would not be treated conservatively.
|
||||
#' * Operators like "<=" will be considered according to the `capped_mic_handling` setting. At default, an MIC value of e.g. ">=2" will return "NI" (non-interpretable) if the breakpoint is 4-8; the *true* MIC could be at either side of the breakpoint. This is to prevent that capped values from raw laboratory data would not be treated conservatively.
|
||||
#' * **Note:** When using CLSI as the guideline, MIC values must be log2-based doubling dilutions. Values not in this format, will be automatically rounded up to the nearest log2 level as CLSI instructs, and a warning will be thrown.
|
||||
#'
|
||||
#' 3. For **interpreting disk diffusion diameters** according to EUCAST or CLSI. You must clean your disk zones first using [as.disk()], that also gives your columns the new data class [`disk`]. Also, be sure to have a column with microorganism names or codes. It will be found automatically, but can be set manually using the `mo` argument.
|
||||
@@ -1860,6 +1862,31 @@ as_sir_method <- function(method_short,
|
||||
)
|
||||
}
|
||||
|
||||
if (isTRUE(substitute_missing_r_breakpoint) && !is.na(breakpoints_current$breakpoint_S) && is.na(breakpoints_current$breakpoint_R)) {
|
||||
# breakpoints_current only has 1 row at this moment
|
||||
breakpoints_current$breakpoint_R <- breakpoints_current$breakpoint_S
|
||||
notes_current <- paste0(
|
||||
notes_current, "\n",
|
||||
ifelse(!is.na(breakpoints_current$breakpoint_S) & is.na(breakpoints_current$breakpoint_R),
|
||||
"NAs because of missing R breakpoints were substituted with R since substitute_missing_r_breakpoint = TRUE.",
|
||||
""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
# EUCAST indicates that there is no S category with an off-scale S breakpoint of 0.001 mg/L (stored as 0.0001 in
|
||||
# clinical_breakpoints), so that wild-type isolates are I; capped MICs such as "<=0.5" must then not be S or NI (#295)
|
||||
no_S_category <- method == "mic" & isTRUE(breakpoints_current$breakpoint_S <= 0.001)
|
||||
middle_sir <- if (isTRUE(breakpoints_current$is_SDD)) as.sir("SDD") else as.sir("I")
|
||||
clsi_closed_R <- !custom_breakpoints_set & guideline_current %like% "CLSI"
|
||||
capped_low_not_R <- (as.character(input_original) %like% "^<[0-9]" & as.double(input_clean) <= breakpoints_current$breakpoint_R) |
|
||||
(as.character(input_original) %like% "^<=[0-9]" & (as.double(input_clean) < breakpoints_current$breakpoint_R |
|
||||
(!clsi_closed_R & as.double(input_clean) == breakpoints_current$breakpoint_R)))
|
||||
capped_low_middle <- capped_mic_handling != "none" & no_S_category & capped_low_not_R %in% TRUE
|
||||
# capped values only get a forced S or R if the guideline has such a category for this drug-bug combination
|
||||
has_S_category <- !is.na(breakpoints_current$breakpoint_S) & !no_S_category
|
||||
has_R_category <- !is.na(breakpoints_current$breakpoint_R)
|
||||
|
||||
notes_current <- paste0(
|
||||
notes_current, "\n",
|
||||
ifelse(breakpoints_current$mo == "UNKNOWN" | breakpoints_current$ref_tbl %like% "PK.*PD",
|
||||
@@ -1879,34 +1906,40 @@ as_sir_method <- function(method_short,
|
||||
""
|
||||
),
|
||||
"\n",
|
||||
ifelse(method == "mic" & capped_mic_handling == "standard" & as.character(input_original) %like% "^[<][0-9]",
|
||||
ifelse(capped_low_middle | (method == "mic" & capped_mic_handling %in% c("standard", "lenient") & no_S_category & has_R_category &
|
||||
as.character(input_original) %like% ifelse(capped_mic_handling == "lenient", "^[<]=?[0-9]", "^[<][0-9]")),
|
||||
paste0("MIC values with the operator '<' or '<=' are considered '", middle_sir, "', not 'S' or 'NI', since the guideline has no S category for this drug-bug combination (off-scale S breakpoint)."),
|
||||
""
|
||||
),
|
||||
"\n",
|
||||
ifelse(method == "mic" & capped_mic_handling == "standard" & has_S_category & as.character(input_original) %like% "^[<][0-9]",
|
||||
paste0("MIC values with the operator '<' are considered 'S' since capped_mic_handling = \"", capped_mic_handling, "\"."),
|
||||
""
|
||||
),
|
||||
"\n",
|
||||
ifelse(method == "mic" & capped_mic_handling == "standard" & as.character(input_original) %like% "^[>][0-9]",
|
||||
ifelse(method == "mic" & capped_mic_handling == "standard" & has_R_category & as.character(input_original) %like% "^[>][0-9]",
|
||||
paste0("MIC values with the operator '>' are considered 'R' since capped_mic_handling = \"", capped_mic_handling, "\"."),
|
||||
""
|
||||
),
|
||||
"\n",
|
||||
ifelse(method == "mic" & capped_mic_handling == "lenient" & as.character(input_original) %like% "^[<]=?[0-9]",
|
||||
ifelse(method == "mic" & capped_mic_handling == "lenient" & has_S_category & as.character(input_original) %like% "^[<]=?[0-9]",
|
||||
paste0("MIC values with the operator '<' or '<=' are considered 'S' since capped_mic_handling = \"", capped_mic_handling, "\"."),
|
||||
""
|
||||
),
|
||||
"\n",
|
||||
ifelse(method == "mic" & capped_mic_handling == "lenient" & as.character(input_original) %like% "^[>]=?[0-9]",
|
||||
ifelse(method == "mic" & capped_mic_handling == "lenient" & has_R_category & as.character(input_original) %like% "^[>]=?[0-9]",
|
||||
paste0("MIC values with the operator '>' or '>=' are considered 'R' since capped_mic_handling = \"", capped_mic_handling, "\"."),
|
||||
""
|
||||
),
|
||||
"\n",
|
||||
ifelse(method == "mic" & capped_mic_handling == "conservative" & as.character(input_original) %like% "^[<>][0-9]" &
|
||||
ifelse(method == "mic" & capped_mic_handling == "conservative" & !capped_low_middle & as.character(input_original) %like% "^[<>][0-9]" &
|
||||
((as.character(input_original) %like% "^<" & as.double(input_clean) > breakpoints_current$breakpoint_S) |
|
||||
(as.character(input_original) %like% "^>" & as.double(input_clean) < breakpoints_current$breakpoint_R)),
|
||||
paste0("MIC values are considered 'NI' (non-interpretable) if the true MIC could be at either side of the breakpoint and capped_mic_handling = \"", capped_mic_handling, "\"."),
|
||||
""
|
||||
),
|
||||
"\n",
|
||||
ifelse(method == "mic" & capped_mic_handling %in% c("conservative", "standard") & as.character(input_original) %like% "^<=[0-9]" & as.double(input_clean) > breakpoints_current$breakpoint_S,
|
||||
ifelse(method == "mic" & capped_mic_handling %in% c("conservative", "standard") & !capped_low_middle & as.character(input_original) %like% "^<=[0-9]" & as.double(input_clean) > breakpoints_current$breakpoint_S,
|
||||
paste0("MIC values are considered 'NI' (non-interpretable) if the true MIC could be at either side of the breakpoint and capped_mic_handling = \"", capped_mic_handling, "\"."),
|
||||
""
|
||||
),
|
||||
@@ -1917,37 +1950,40 @@ as_sir_method <- function(method_short,
|
||||
)
|
||||
)
|
||||
|
||||
if (isTRUE(substitute_missing_r_breakpoint) && !is.na(breakpoints_current$breakpoint_S) && is.na(breakpoints_current$breakpoint_R)) {
|
||||
# breakpoints_current only has 1 row at this moment
|
||||
breakpoints_current$breakpoint_R <- breakpoints_current$breakpoint_S
|
||||
notes_current <- paste0(
|
||||
notes_current, "\n",
|
||||
ifelse(!is.na(breakpoints_current$breakpoint_S) & is.na(breakpoints_current$breakpoint_R),
|
||||
"NAs because of missing R breakpoints were substituted with R since substitute_missing_r_breakpoint = TRUE.",
|
||||
""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
## actual interpretation ----
|
||||
if (method == "mic") {
|
||||
new_sir <- case_when_AMR(
|
||||
is.na(input_clean) ~ NA_sir_,
|
||||
|
||||
# "lenient" for any cap: force S/R
|
||||
# no S category: capped values that cannot be R are I (or SDD), regardless of capped_mic_handling (#295)
|
||||
capped_low_middle ~ middle_sir,
|
||||
|
||||
# "lenient" for any cap: force S/R, or I/SDD if there is no S category
|
||||
capped_mic_handling == "lenient" &
|
||||
as.character(input_original) %like% "^[<]=?[0-9]"
|
||||
as.character(input_original) %like% "^[<]=?[0-9]" &
|
||||
no_S_category & has_R_category
|
||||
~ middle_sir,
|
||||
capped_mic_handling == "lenient" &
|
||||
as.character(input_original) %like% "^[<]=?[0-9]" &
|
||||
has_S_category
|
||||
~ as.sir("S"),
|
||||
capped_mic_handling == "lenient" &
|
||||
as.character(input_original) %like% "^[>]=?[0-9]"
|
||||
as.character(input_original) %like% "^[>]=?[0-9]" &
|
||||
has_R_category
|
||||
~ as.sir("R"),
|
||||
|
||||
# "standard" for < and >: force S/R
|
||||
# "standard" for < and >: force S/R, or I/SDD if there is no S category
|
||||
capped_mic_handling == "standard" &
|
||||
as.character(input_original) %like% "^[<][0-9]"
|
||||
as.character(input_original) %like% "^[<][0-9]" &
|
||||
no_S_category & has_R_category
|
||||
~ middle_sir,
|
||||
capped_mic_handling == "standard" &
|
||||
as.character(input_original) %like% "^[<][0-9]" &
|
||||
has_S_category
|
||||
~ as.sir("S"),
|
||||
capped_mic_handling == "standard" &
|
||||
as.character(input_original) %like% "^[>][0-9]"
|
||||
as.character(input_original) %like% "^[>][0-9]" &
|
||||
has_R_category
|
||||
~ as.sir("R"),
|
||||
|
||||
# "conservative" for < and >: NI if the true MIC could be on either side of a breakpoint
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ This is an overview of all the package-specific options you can set in the \code
|
||||
\itemize{
|
||||
\item \code{AMR_antibiogram_formatting_type} \cr A \link{numeric} (1-22) to use in \code{\link[=antibiogram]{antibiogram()}}, to indicate which formatting type to use.
|
||||
\item \code{AMR_breakpoint_type} \cr A \link{character} to use in \code{\link[=as.sir]{as.sir()}}, to indicate which breakpoint type to use. This must be either \code{"ECOFF"}, \code{"animal"}, or \code{"human"}.
|
||||
\item \code{AMR_capped_mic_handling} \cr A \link{character} to use in \code{\link[=as.sir]{as.sir()}}, to indicate how capped MIC values (\code{<}, \code{<=}, \code{>}, \code{>=}) should be interpreted. Must be one of \code{"none"}, \code{"conservative"}, \code{"standard"}, or \code{"lenient"} - the default is \code{"conservative"}.
|
||||
\item \code{AMR_capped_mic_handling} \cr A \link{character} to use in \code{\link[=as.sir]{as.sir()}}, to indicate how capped MIC values (\code{<}, \code{<=}, \code{>}, \code{>=}) should be interpreted. Must be one of \code{"none"}, \code{"conservative"}, \code{"standard"}, or \code{"lenient"} - the default is \code{"standard"}.
|
||||
\item \code{AMR_cleaning_regex} \cr A \link[base:regex]{regular expression} (case-insensitive) to use in \code{\link[=as.mo]{as.mo()}} and all \code{\link[=mo_property]{mo_*}} functions, to clean the user input. The default is the outcome of \code{\link[=mo_cleaning_regex]{mo_cleaning_regex()}}, which removes texts between brackets and texts such as "species" and "serovar".
|
||||
\item \code{AMR_custom_ab} \cr A file location to an RDS file, to use custom antimicrobial drugs with this package. This is explained in \code{\link[=add_custom_antimicrobials]{add_custom_antimicrobials()}}.
|
||||
\item \code{AMR_custom_mo} \cr A file location to an RDS file, to use custom microorganisms with this package. This is explained in \code{\link[=add_custom_microorganisms]{add_custom_microorganisms()}}.
|
||||
|
||||
+6
-4
@@ -134,13 +134,13 @@ Otherwise: arguments passed on to methods.}
|
||||
\item \code{<=}, \code{<}, \code{>} and \code{>=} are ignored.
|
||||
}
|
||||
|
||||
\code{"conservative"} (default)
|
||||
\code{"conservative"}
|
||||
\itemize{
|
||||
\item \code{<=}, \code{<}, \code{>} and \code{>=} return \code{"NI"} (non-interpretable) if the \emph{true} MIC could be at either side of the breakpoint.
|
||||
\item This is the only mode that preserves uncertainty for ECOFFs.
|
||||
}
|
||||
|
||||
\code{"standard"}
|
||||
\code{"standard"} (default)
|
||||
\itemize{
|
||||
\item \code{<=} and \code{>=} return \code{"NI"} (non-interpretable) if the \emph{true} MIC could be at either side of the breakpoint.
|
||||
\item \code{<} always returns \code{"S"}, regardless of the breakpoint.
|
||||
@@ -153,7 +153,9 @@ Otherwise: arguments passed on to methods.}
|
||||
\item \code{>=} and \code{>} always return \code{"R"}, regardless of the breakpoint.
|
||||
}
|
||||
|
||||
The default \code{"conservative"} setting ensures cautious handling of uncertain values while preserving interpretability. This option can also be set with the package option \code{\link[=AMR-options]{AMR_capped_mic_handling}}.}
|
||||
In all modes except \code{"none"}, a capped value is never forced to a category that the guideline does not provide for the drug-bug combination: if a breakpoint is missing, the result is \code{NA} as for uncapped values. EUCAST uses an off-scale S breakpoint of 0.001 mg/L to indicate that there is no S category (stored as 0.0001 in \link{clinical_breakpoints}; any S breakpoint of 0.001 or lower is treated as such). In that case, \code{<} and \code{<=} values that cannot be \code{"R"} return \code{"I"} (or \code{"SDD"}), and \code{"standard"} and \code{"lenient"} return \code{"I"} (or \code{"SDD"}) instead of \code{"S"}.
|
||||
|
||||
The default \code{"standard"} setting ensures cautious handling of uncertain values while preserving interpretability. This option can also be set with the package option \code{\link[=AMR-options]{AMR_capped_mic_handling}}.}
|
||||
|
||||
\item{as_wt_nwt}{A \link{logical} to return \code{"WT"}/\code{"NWT"} instead of \code{"S"}/\code{"R"}. Defaults to \code{TRUE} when using ECOFFs, i.e., when \code{breakpoint_type} is set to \code{"ECOFF"}.}
|
||||
|
||||
@@ -213,7 +215,7 @@ your_data \%>\% mutate_if(is.mic, as.sir, host = "column_with_animal_species", g
|
||||
# fast processing with parallel computing (requires future.apply):
|
||||
as.sir(your_data, ..., parallel = TRUE)
|
||||
}\if{html}{\out{</div>}}
|
||||
\item Operators like "<=" will be considered according to the \code{capped_mic_handling} setting. At default, an MIC value of e.g. ">2" will return "NI" (non-interpretable) if the breakpoint is 4-8; the \emph{true} MIC could be at either side of the breakpoint. This is to prevent that capped values from raw laboratory data would not be treated conservatively.
|
||||
\item Operators like "<=" will be considered according to the \code{capped_mic_handling} setting. At default, an MIC value of e.g. ">=2" will return "NI" (non-interpretable) if the breakpoint is 4-8; the \emph{true} MIC could be at either side of the breakpoint. This is to prevent that capped values from raw laboratory data would not be treated conservatively.
|
||||
\item \strong{Note:} When using CLSI as the guideline, MIC values must be log2-based doubling dilutions. Values not in this format, will be automatically rounded up to the nearest log2 level as CLSI instructs, and a warning will be thrown.
|
||||
}
|
||||
\item For \strong{interpreting disk diffusion diameters} according to EUCAST or CLSI. You must clean your disk zones first using \code{\link[=as.disk]{as.disk()}}, that also gives your columns the new data class \code{\link{disk}}. Also, be sure to have a column with microorganism names or codes. It will be found automatically, but can be set manually using the \code{mo} argument.
|
||||
|
||||
@@ -406,6 +406,41 @@ test_that("test-sir.R", {
|
||||
expect_equal(out3, as.sir(c("NWT", "WT", "NWT")))
|
||||
expect_equal(out4, as.sir(c("NWT", "WT", "NWT")))
|
||||
|
||||
# Issue #295: no S category (off-scale S breakpoint), e.g. EUCAST CIP in P. aeruginosa (S <= 0.001, R > 0.5)
|
||||
capped_psa <- as.mic(c("<=0.5", "<0.5", "<=0.25", "<0.25", "<=0.001", "<=1", "<1", ">=0.5", ">0.5", "0.25"))
|
||||
capped_psa_sir <- function(handling) {
|
||||
suppressMessages(as.sir(capped_psa, mo = "Pseudomonas aeruginosa", ab = "CIP", guideline = "EUCAST 2026", capped_mic_handling = handling))
|
||||
}
|
||||
expect_equal(capped_psa_sir("none"), as.sir(c("I", "I", "I", "I", "I", "R", "R", "I", "R", "I")))
|
||||
expect_equal(capped_psa_sir("conservative"), as.sir(c("I", "I", "I", "I", "I", "NI", "NI", "NI", "R", "I")))
|
||||
expect_equal(capped_psa_sir("standard"), as.sir(c("I", "I", "I", "I", "I", "NI", "I", "NI", "R", "I")))
|
||||
expect_equal(capped_psa_sir("lenient"), as.sir(c("I", "I", "I", "I", "I", "I", "I", "R", "R", "I")))
|
||||
# the same with custom reference data that uses the off-scale value as printed by EUCAST (S <= 0.001, R > 2)
|
||||
ref_staph <- subset(clinical_breakpoints, guideline == "EUCAST 2026" & ab == "CIP" & mo == "B_PSDMN" & method == "MIC" & type == "human")[1, , drop = FALSE]
|
||||
ref_staph$mo <- as.mo("B_STPHY_AURS")
|
||||
ref_staph$breakpoint_S <- 0.001
|
||||
ref_staph$breakpoint_R <- 2
|
||||
for (handling in c("conservative", "standard", "lenient")) {
|
||||
expect_equal(
|
||||
suppressMessages(as.sir(as.mic(c("<=0.5", "<0.5", "<=2", "<0.001")), mo = "Staphylococcus aureus", ab = "CIP", reference_data = ref_staph, capped_mic_handling = handling)),
|
||||
as.sir(c("I", "I", "I", "I"))
|
||||
)
|
||||
}
|
||||
# SDD as middle category, e.g. CLSI DAP in E. faecium (SDD <= 4, R >= 8)
|
||||
expect_equal(
|
||||
suppressMessages(as.sir(as.mic(c("<=4", "<=2", "<=0.5")), mo = "Enterococcus faecium", ab = "DAP", guideline = "CLSI 2026", capped_mic_handling = "lenient")),
|
||||
as.sir(c("SDD", "SDD", "SDD"))
|
||||
)
|
||||
# an S category remains unaffected, e.g. EUCAST CIP in E. coli (S <= 0.25, R > 0.5)
|
||||
expect_equal(
|
||||
suppressMessages(as.sir(as.mic(c("<=0.5", "<0.5", "<=0.25")), mo = "Escherichia coli", ab = "CIP", guideline = "EUCAST 2026", capped_mic_handling = "standard")),
|
||||
as.sir(c("NI", "S", "S"))
|
||||
)
|
||||
# capped values must not be forced to S or R if there is no breakpoint (blocking row, here: EUCAST CIP in S. aureus in brackets only)
|
||||
for (handling in c("none", "conservative", "standard", "lenient")) {
|
||||
expect_true(all(is.na(suppressMessages(as.sir(as.mic(c("<0.5", "<=0.5", ">2", ">=2", "1")), mo = "Staphylococcus aureus", ab = "CIP", guideline = "EUCAST 2026", capped_mic_handling = handling)))))
|
||||
}
|
||||
|
||||
# Issue #278: re-running as.sir() on already-<sir> data must preserve columns
|
||||
df_already_sir <- data.frame(
|
||||
mo = "B_ESCHR_COLI",
|
||||
|
||||
Reference in new issue
Block a user