mirror of
https://github.com/msberends/AMR.git
synced 2026-05-31 12:21:40 +02:00
Compare commits
4 Commits
ee6fab9b50
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0af3f84655 | |||
|
|
64753e9a16 | ||
|
|
24f24ecaf8 | ||
|
|
f7e9294bea |
@@ -1,6 +1,6 @@
|
||||
Package: AMR
|
||||
Version: 3.0.1.9055
|
||||
Date: 2026-04-30
|
||||
Version: 3.0.1.9057
|
||||
Date: 2026-05-02
|
||||
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
|
||||
|
||||
@@ -49,6 +49,7 @@ S3method(as.data.frame,mo)
|
||||
S3method(as.double,mic)
|
||||
S3method(as.double,sir)
|
||||
S3method(as.list,custom_eucast_rules)
|
||||
S3method(as.list,custom_interpretive_rules)
|
||||
S3method(as.list,custom_mdro_guideline)
|
||||
S3method(as.list,mic)
|
||||
S3method(as.matrix,mic)
|
||||
@@ -66,6 +67,7 @@ S3method(c,ab)
|
||||
S3method(c,amr_selector)
|
||||
S3method(c,av)
|
||||
S3method(c,custom_eucast_rules)
|
||||
S3method(c,custom_interpretive_rules)
|
||||
S3method(c,custom_mdro_guideline)
|
||||
S3method(c,disk)
|
||||
S3method(c,mic)
|
||||
@@ -96,6 +98,7 @@ S3method(print,amr_selector)
|
||||
S3method(print,av)
|
||||
S3method(print,bug_drug_combinations)
|
||||
S3method(print,custom_eucast_rules)
|
||||
S3method(print,custom_interpretive_rules)
|
||||
S3method(print,custom_mdro_guideline)
|
||||
S3method(print,deprecated_amr_dataset)
|
||||
S3method(print,disk)
|
||||
@@ -228,6 +231,7 @@ export(count_df)
|
||||
export(count_resistant)
|
||||
export(count_susceptible)
|
||||
export(custom_eucast_rules)
|
||||
export(custom_interpretive_rules)
|
||||
export(custom_mdro_guideline)
|
||||
export(eucast_dosage)
|
||||
export(eucast_exceptional_phenotypes)
|
||||
|
||||
80
NEWS.md
80
NEWS.md
@@ -1,65 +1,35 @@
|
||||
# AMR 3.0.1.9055
|
||||
# AMR 3.0.1.9057
|
||||
|
||||
This will become release v3.1.0, intended for launch end of May.
|
||||
Planned as v3.1.0, May 2026.
|
||||
|
||||
### New
|
||||
* Support for clinical breakpoints of 2026 of both CLSI and EUCAST, by adding all of their over 5,700 new clinical breakpoints to the `clinical_breakpoints` data set for usage in `as.sir()`. EUCAST 2026 is now the new default guideline for all MIC and disk diffusion interpretations.
|
||||
* Support for the [`future`](https://future.futureverse.org) package and its framework, as the previous implementation of parallel computing was slow
|
||||
- **Breaking change**: `as.sir()` with `parallel = TRUE` now requires a non-sequential `future::plan()` to be active before the call — e.g., `future::plan(future::multisession)` — and throws an informative error if none is set.
|
||||
- New all-core usage setup: when the number of AB columns is smaller than the number of available cores, rows are now split into batches so all cores stay active (row-batch mode). Previously, a 6-column dataset on a 16-core machine would only use 6 cores; now all 16 are used, with each worker processing a smaller row slice (lower per-worker memory pressure and processing time)
|
||||
- `antibiogram()` and `wisca()` gained a `parallel` argument using the same `future`/`future.apply` pattern: for WISCA, Monte Carlo simulations are split into `(group, chunk)` job pairs distributed across workers; for grouped antibiograms, each group is processed by a separate worker (#281)
|
||||
* Integration with the *tidymodels* framework to allow seamless use of SIR, MIC and disk data in modelling pipelines via `recipes`
|
||||
- `step_mic_log2()` to transform `<mic>` columns with log2, and `step_sir_numeric()` to convert `<sir>` columns to numeric
|
||||
- New `tidyselect` helpers:
|
||||
- `all_sir()`, `all_sir_predictors()`
|
||||
- `all_mic()`, `all_mic_predictors()`
|
||||
- `all_disk()`, `all_disk_predictors()`
|
||||
* Data set `esbl_isolates` to practise with AMR modelling
|
||||
* AMR selectors `ionophores()`, `peptides()`, `phosphonics()` and `spiropyrimidinetriones()`
|
||||
* Support for Wildtype (WT) / Non-wildtype (NWT) in `as.sir()`, all plotting functions, and all susceptibility/resistance functions.
|
||||
- `as.sir()` gained an argument `as_wt_nwt`, which defaults to `TRUE` only when `breakpoint_type = "ECOFF"` (#254)
|
||||
- This transforms the output from S/R to WT/NWT
|
||||
- Functions such as `susceptibility()` count WT as S and NWT as R
|
||||
* Function `interpretive_rules()`, which allows future implementation of CLSI interpretive rules (#235)
|
||||
- `eucast_rules()` has become a wrapper around that function
|
||||
- Gained argument `add_if_missing` (default: `TRUE`). When set to `FALSE`, rules are only applied to cells that already contain an SIR value; `NA` cells are left untouched. This is useful with `overwrite = TRUE` to update reported results without imputing values for drugs that were not tested (#259)
|
||||
* Function `amr_course()`, which allows for automated download and unpacking of a GitHub repository for e.g. webinar use
|
||||
* 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
|
||||
* EUCAST 2026 and CLSI 2026 breakpoints: over 5,700 new breakpoints added to the `clinical_breakpoints` data set; EUCAST 2026 is now the default for all MIC and disk diffusion interpretations
|
||||
* Wildtype/Non-wildtype (WT/NWT) output when using ECOFF-based interpretation, by setting `breakpoint_type = "ECOFF"` in `as.sir()`; WT/NWT results are fully supported in all resistance/susceptibility functions and plots (#254)
|
||||
* Faster parallel computing via the `future` package; **breaking change**: a non-sequential plan (e.g. `future::plan(future::multisession)`) must be active before using `parallel = TRUE`; `antibiogram()` and `wisca()` now also support `parallel = TRUE` (#281)
|
||||
* *tidymodels* integration for using SIR, MIC and disk data in modelling pipelines: `step_mic_log2()`, `step_sir_numeric()`, and new column selectors `all_sir()`, `all_mic()`, `all_disk()`
|
||||
* New `esbl_isolates` data set for practising AMR modelling
|
||||
* New antimicrobial selectors: `ionophores()`, `peptides()`, `phosphonics()`, `spiropyrimidinetriones()`
|
||||
* New `interpretive_rules()`, a unified function for EUCAST and CLSI interpretive rules; `eucast_rules()` is now a wrapper around it (#235, #259)
|
||||
* New `amr_course()` to download and unpack course or webinar materials from GitHub in one call
|
||||
* Typed missing value constants `NA_ab_` and `NA_mo_`, for use in pipelines that need missing values of a specific class
|
||||
|
||||
### Fixes
|
||||
* 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.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 `antibiogram()` for when no antimicrobials are set
|
||||
* Fixed a bug in `as.sir()` where for numeric input the arguments `S`, `I`, and `R` would not be considered (#244)
|
||||
* Fixed a bug in plotting MIC values when `keep_operators = "all"`
|
||||
* Fixed some foreign translations of antimicrobial drugs
|
||||
* Fixed a bug for printing column names to the console when using `mutate_at(vars(...), as.mic)` (#249)
|
||||
* Fixed a bug to disregard `NI` for susceptibility proportion functions
|
||||
* Fixed Italian translation of CoNS to Stafilococco coagulasi-negativo and CoPS to Stafilococco coagulasi-positivo (#256)
|
||||
* Fixed SIR and MIC coercion of combined values, e.g. `as.sir("<= 0.002; S") ` or `as.mic("S; 0.002")` (#252)
|
||||
* Fixed translation of foreign languages in `sir_df()` (#272)
|
||||
* Fixed BRMO classification by including bacterial complexes (#275)
|
||||
* Fixed `as.sir()` for data frames silently deleting columns whose AB class was already `<sir>` when called a second time (re-running on already-converted data) (#278)
|
||||
* Fixed `as.sir()` for data frames incorrectly treating metadata columns (e.g. `patient`, `ward`) as antibiotic columns when their names coincidentally matched an antibiotic code; column content is now validated against AMR data patterns before inclusion
|
||||
* Fixed `as.sir()` ignoring `info = FALSE` for columns with no breakpoints (e.g. cefoxitin against *E. coli*)
|
||||
* `as.sir()` on data frames: already-converted SIR columns no longer dropped on re-run (#278); metadata columns (e.g. `patient`, `ward`) no longer misidentified as antibiotic columns; `info = FALSE` now suppresses all messages, including for columns without breakpoints
|
||||
* `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)
|
||||
* Combined MIC/SIR input values (e.g. `"<= 0.002; S"` or `"S; 0.002"`) now parsed correctly (#252)
|
||||
* BRMO classification now includes bacterial complexes (#275)
|
||||
* Translation fixes for Italian CoNS/CoPS names (#256), Dutch antimicrobials, and `sir_df()` foreign-language output (#272)
|
||||
|
||||
### Updates
|
||||
* `as.sir()` with `reference_data`: custom guideline names now correctly classify values as R using EUCAST convention (`> breakpoint_R` for MIC, `< breakpoint_R` for disk); custom breakpoints with `host = NA` now serve as a host-agnostic fallback when no host-specific row matches (#239)
|
||||
* Extensive `cli` integration for better message handling and clickable links in messages and warnings (#191, #265)
|
||||
* `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.
|
||||
* Added to the `antimicrobials` data set: cefepime/taniborbactam (`FTA`), ceftibuten/avibactam (`CTA`), clorobiocin (`CLB`), kasugamycin (`KAS`), ostreogrycin (`OST`), taniborbactam (`TAN`), thiostrepton (`THS`), xeruborbactam (`XER`), and zorbamycin (`ZOR`)
|
||||
* `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)
|
||||
* `ab_group()` gained an argument `all_groups` to return all groups the antimicrobial drug is in (#246)
|
||||
* Added explaining message to `as.sir()` when interpreting numeric values (e.g., 1 for S, 2 for I, 3 for R) (#244)
|
||||
* Updated handling of capped MIC values (`<`, `<=`, `>`, `>=`) in `as.sir()` in the argument `capped_mic_handling`: (#243)
|
||||
* Introduced four clearly defined options: `"none"`, `"conservative"` (default), `"standard"`, and `"lenient"`
|
||||
* Interpretation of capped MIC values now consistently returns `"NI"` (non-interpretable) when the true MIC could be at either side of a breakpoint, depending on the selected handling mode
|
||||
* This results in more reliable behaviour compared to previous versions for capped MIC values
|
||||
* Removed the `"inverse"` option, which has now become redundant
|
||||
* `ab_group()` now returns values consist with the AMR selectors (#246)
|
||||
* `custom_eucast_rules()` renamed to `custom_interpretive_rules()`; old name deprecated but still works (#268)
|
||||
* `mdro()` can now infer resistance from a drug+inhibitor combination when the base drug column is absent (e.g. piperacillin inferred from piperacillin/tazobactam); controlled via new `infer_from_combinations` argument (default `TRUE`) (#209)
|
||||
* `susceptibility()` / `resistance()`: new `guideline` argument (default EUCAST) to ensure the 'I' category is interpreted correctly per guideline
|
||||
* Capped MIC handling in `as.sir()` reworked into four clearly defined options: `"none"`, `"conservative"` (new default), `"standard"`, `"lenient"` (#243)
|
||||
* `as.mic()` / `rescale_mic()`: new `round_to_next_log2` argument to round values up to the nearest log2 dilution level (#255)
|
||||
* `antimicrobials$group` now a `list`, so drugs belonging to multiple groups are fully represented; use `ab_group(all_groups = TRUE)` to retrieve all groups for a drug (#246)
|
||||
* New antimicrobials added: cefepime/taniborbactam (`FTA`), ceftibuten/avibactam (`CTA`), clorobiocin (`CLB`), kasugamycin (`KAS`), ostreogrycin (`OST`), taniborbactam (`TAN`), thiostrepton (`THS`), xeruborbactam (`XER`), zorbamycin (`ZOR`)
|
||||
* Improved console messages with clickable links throughout, powered by `cli` (#191, #265)
|
||||
|
||||
|
||||
# AMR 3.0.1
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
# add new version numbers here, and add the rules themselves to "data-raw/eucast_rules.tsv" and clinical_breakpoints
|
||||
# add new version numbers here, and add the rules themselves to "data-raw/interpretive_rules.tsv" and clinical_breakpoints
|
||||
# (sourcing "data-raw/_pre_commit_checks.R" will process the TSV file)
|
||||
EUCAST_VERSION_BREAKPOINTS <- list(
|
||||
"16.0" = list(
|
||||
@@ -221,6 +221,7 @@ globalVariables(c(
|
||||
"reference.rule",
|
||||
"reference.rule_group",
|
||||
"reference.version",
|
||||
"rule.provider",
|
||||
"rowid",
|
||||
"rule_group",
|
||||
"rule_name",
|
||||
|
||||
0
R/aa_helper_functions.R
Normal file → Executable file
0
R/aa_helper_functions.R
Normal file → Executable file
0
R/amr_course.R
Normal file → Executable file
0
R/amr_course.R
Normal file → Executable file
@@ -54,7 +54,7 @@
|
||||
#' @param add_total_n *(deprecated in favour of `formatting_type`)* A [logical] to indicate whether `n_tested` available numbers per pathogen should be added to the table (default is `TRUE`). This will add the lowest and highest number of available isolates per antimicrobial (e.g, if for *E. coli* 200 isolates are available for ciprofloxacin and 150 for amoxicillin, the returned number will be "150-200"). This option is unavailable when `wisca = TRUE`; in that case, use [retrieve_wisca_parameters()] to get the parameters used for WISCA.
|
||||
#' @param only_all_tested (for combination antibiograms): a [logical] to indicate that isolates must be tested for all antimicrobials, see *Details*.
|
||||
#' @param digits Number of digits to use for rounding the antimicrobial coverage, defaults to 1 for WISCA and 0 otherwise.
|
||||
#' @param formatting_type Numeric value (1–22 for WISCA, 1-12 for non-WISCA) indicating how the 'cells' of the antibiogram table should be formatted. See *Details* > *Formatting Type* for a list of options.
|
||||
#' @param formatting_type Numeric value (1-22 for WISCA, 1-12 for non-WISCA) indicating how the 'cells' of the antibiogram table should be formatted. See *Details* > *Formatting Type* for a list of options.
|
||||
#' @param col_mo Column name of the names or codes of the microorganisms (see [as.mo()]) - the default is the first column of class [`mo`]. Values will be coerced using [as.mo()].
|
||||
#' @param language Language to translate text, which defaults to the system language (see [get_AMR_locale()]).
|
||||
#' @param minimum The minimum allowed number of available (tested) isolates. Any isolate count lower than `minimum` will return `NA` with a warning. The default number of `30` isolates is advised by the Clinical and Laboratory Standards Institute (CLSI) as best practice, see *Source*.
|
||||
@@ -65,7 +65,7 @@
|
||||
#' @param simulations (for WISCA) a numerical value to set the number of Monte Carlo simulations.
|
||||
#' @param conf_interval A numerical value to set confidence interval (default is `0.95`).
|
||||
#' @param interval_side The side of the confidence interval, either `"two-tailed"` (default), `"left"` or `"right"`.
|
||||
#' @param parallel A [logical] to indicate if parallel computing must be used, defaults to `FALSE`. Requires the [`future.apply`][future.apply::future_lapply()] package. For WISCA, Monte Carlo simulations are distributed across workers; for grouped antibiograms, each group is processed by a separate worker. **A non-sequential [future::plan()] must already be active before setting `parallel = TRUE`** — for example, `future::plan(future::multisession)`. An error is thrown if `parallel = TRUE` is used without a plan set by the user.
|
||||
#' @param parallel A [logical] to indicate if parallel computing must be used, defaults to `FALSE`. Requires the [`future.apply`][future.apply::future_lapply()] package. For WISCA, Monte Carlo simulations are distributed across workers; for grouped antibiograms, each group is processed by a separate worker. **A non-sequential [future::plan()] must already be active before setting `parallel = TRUE`** -- for example, `future::plan(future::multisession)`. An error is thrown if `parallel = TRUE` is used without a plan set by the user.
|
||||
#' @param info A [logical] to indicate info should be printed - the default is `TRUE` only in interactive mode.
|
||||
#' @param object An [antibiogram()] object.
|
||||
#' @param ... When used in [R Markdown or Quarto][knitr::kable()]: arguments passed on to [knitr::kable()] (otherwise, has no use).
|
||||
@@ -483,6 +483,34 @@ antibiogram.default <- function(x,
|
||||
meet_criteria(info, allow_class = "logical", has_length = 1)
|
||||
meet_criteria(parallel, allow_class = "logical", has_length = 1)
|
||||
|
||||
# parallel gate - identical pattern to as.sir()
|
||||
if (requireNamespace("future.apply", quietly = TRUE) && !inherits(future::plan(), "sequential")) {
|
||||
if (isFALSE(parallel)) {
|
||||
message_("Assuming {.code parallel = TRUE} since parallel computing has been set up using the {.pkg future} package before. Set {.help [{.fun plan}](future::plan)} to sequential to prevent this.")
|
||||
}
|
||||
parallel <- TRUE
|
||||
}
|
||||
if (isTRUE(parallel)) {
|
||||
stop_ifnot(
|
||||
requireNamespace("future.apply", quietly = TRUE),
|
||||
"Setting {.code parallel = TRUE} requires the {.pkg future.apply} package.\n",
|
||||
"Install it with {.code install.packages(\"future.apply\")}."
|
||||
)
|
||||
stop_if(inherits(future::plan(), "sequential"),
|
||||
"Setting {.code parallel = TRUE} requires a non-sequential {.help [{.fun future::plan}](future::plan)} to be active.\n",
|
||||
"For your system, you could first run: {.code library(future); ",
|
||||
ifelse(.Platform$OS.type == "windows" || in_rstudio(),
|
||||
"plan(multisession)",
|
||||
"plan(multicore)"
|
||||
),
|
||||
"}",
|
||||
call = FALSE
|
||||
)
|
||||
n_workers <- future::nbrOfWorkers()
|
||||
} else {
|
||||
n_workers <- 1L
|
||||
}
|
||||
|
||||
# try to find columns based on type
|
||||
if (is.null(col_mo)) {
|
||||
col_mo <- search_type_in_df(x = x, type = "mo", info = info)
|
||||
@@ -718,35 +746,7 @@ antibiogram.default <- function(x,
|
||||
c(1 - conf_interval, 1)
|
||||
}
|
||||
|
||||
unique_groups <- unique(wisca_parameters$group)
|
||||
|
||||
# parallel gate for WISCA — identical pattern to as.sir()
|
||||
if (requireNamespace("future.apply", quietly = TRUE) && !inherits(future::plan(), "sequential")) {
|
||||
if (isFALSE(parallel)) {
|
||||
message_("Assuming {.code parallel = TRUE} since parallel computing has been set up using the {.pkg future} package before. Set {.help [{.fun plan}](future::plan)} to sequential to prevent this.")
|
||||
}
|
||||
parallel <- TRUE
|
||||
}
|
||||
if (isTRUE(parallel)) {
|
||||
stop_ifnot(
|
||||
requireNamespace("future.apply", quietly = TRUE),
|
||||
"Setting {.code parallel = TRUE} requires the {.pkg future.apply} package.\n",
|
||||
"Install it with {.code install.packages(\"future.apply\")}."
|
||||
)
|
||||
stop_if(inherits(future::plan(), "sequential"),
|
||||
"Setting {.code parallel = TRUE} requires a non-sequential {.help [{.fun future::plan}](future::plan)} to be active.\n",
|
||||
"For your system, you could first run: {.code library(future); ",
|
||||
ifelse(.Platform$OS.type == "windows" || in_rstudio(),
|
||||
"plan(multisession)",
|
||||
"plan(multicore)"
|
||||
),
|
||||
"}",
|
||||
call = FALSE
|
||||
)
|
||||
n_workers <- future::nbrOfWorkers()
|
||||
} else {
|
||||
n_workers <- 1L
|
||||
}
|
||||
unique_groups <- as.character(unique(wisca_parameters$group))
|
||||
|
||||
use_parallel_wisca <- isTRUE(parallel) && n_workers > 1L && length(unique_groups) > 0L
|
||||
|
||||
@@ -762,7 +762,9 @@ antibiogram.default <- function(x,
|
||||
# precompute priors per group and build (group, chunk) job list
|
||||
jobs <- unlist(lapply(unique_groups, function(g) {
|
||||
params_g <- wisca_parameters[wisca_parameters$group == g, , drop = FALSE]
|
||||
if (sum(params_g$n_tested, na.rm = TRUE) == 0L) return(NULL)
|
||||
if (sum(params_g$n_tested, na.rm = TRUE) == 0L) {
|
||||
return(NULL)
|
||||
}
|
||||
priors_g <- create_wisca_priors(params_g)
|
||||
lapply(seq_along(chunk_sizes), function(ch) {
|
||||
list(group = g, priors = priors_g, n_sims = chunk_sizes[ch])
|
||||
@@ -787,8 +789,7 @@ antibiogram.default <- function(x,
|
||||
out_wisca$upper_ci[out_wisca$group == g] <- ci_vals[2]
|
||||
}
|
||||
|
||||
if (isTRUE(info)) message_(font_green_bg(" DONE "), as_note = FALSE)
|
||||
|
||||
if (isTRUE(info)) message_(font_green_bg(" DONE "), as_note = FALSE)
|
||||
} else {
|
||||
progress <- progress_ticker(
|
||||
n = length(unique_groups) * simulations,
|
||||
@@ -815,6 +816,17 @@ antibiogram.default <- function(x,
|
||||
out_wisca$upper_ci[out_wisca$group == group] <- ci_vals[2]
|
||||
}
|
||||
close(progress)
|
||||
if (isTRUE(info) && simulations >= 500 && length(unique_groups) >= 3) {
|
||||
suggest <- ifelse(.Platform$OS.type == "windows" || in_rstudio(),
|
||||
"plan(multisession)",
|
||||
"plan(multicore)"
|
||||
)
|
||||
if (requireNamespace("future.apply", quietly = TRUE)) {
|
||||
message_("Running in sequential mode. To speed up WISCA, set a parallel {.help [{.fun future::plan}](future::plan)} such as {.code ", suggest, "} and use {.code parallel = TRUE}.")
|
||||
} else {
|
||||
message_("Running in sequential mode. To speed up WISCA, install the {.pkg future.apply} package and then set {.code parallel = TRUE}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# final output preparation
|
||||
@@ -1071,7 +1083,7 @@ antibiogram.grouped_df <- function(x,
|
||||
groups <- attributes(x)$groups
|
||||
n_groups <- NROW(groups)
|
||||
|
||||
# parallel gate — identical pattern to as.sir()
|
||||
# parallel gate - identical pattern to as.sir()
|
||||
if (requireNamespace("future.apply", quietly = TRUE) && !inherits(future::plan(), "sequential")) {
|
||||
if (isFALSE(parallel)) {
|
||||
message_("Assuming {.code parallel = TRUE} since parallel computing has been set up using the {.pkg future} package before. Set {.help [{.fun plan}](future::plan)} to sequential to prevent this.")
|
||||
@@ -1104,7 +1116,9 @@ antibiogram.grouped_df <- function(x,
|
||||
x_df <- as.data.frame(x)
|
||||
run_group <- function(i) {
|
||||
rows <- unlist(groups[i, ]$.rows)
|
||||
if (length(rows) == 0L) return(NULL)
|
||||
if (length(rows) == 0L) {
|
||||
return(NULL)
|
||||
}
|
||||
antibiogram(x_df[rows, , drop = FALSE],
|
||||
antimicrobials = antimicrobials,
|
||||
mo_transform = NULL,
|
||||
@@ -1125,7 +1139,7 @@ antibiogram.grouped_df <- function(x,
|
||||
conf_interval = conf_interval,
|
||||
interval_side = interval_side,
|
||||
info = FALSE,
|
||||
parallel = FALSE # never nest parallelism in workers
|
||||
parallel = FALSE # never nest parallelism in workers
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,27 +27,27 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
#' Define Custom EUCAST Rules
|
||||
#' Define Custom Interpretive Rules
|
||||
#'
|
||||
#' Define custom EUCAST rules for your organisation or specific analysis and use the output of this function in [eucast_rules()].
|
||||
#' Define custom interpretive rules for your organisation or specific analysis and use the output of this function in [interpretive_rules()].
|
||||
#' @param ... Rules in [formula][base::tilde] notation, see below for instructions, and in *Examples*.
|
||||
#' @details
|
||||
#' Some organisations have their own adoption of EUCAST rules. This function can be used to define custom EUCAST rules to be used in the [eucast_rules()] function.
|
||||
#' Some organisations have their own adoption of interpretive rules. This function can be used to define custom rules to be used in the [interpretive_rules()] function.
|
||||
#'
|
||||
#' ### Basics
|
||||
#'
|
||||
#' If you are familiar with the [`case_when()`][dplyr::case_when()] function of the `dplyr` package, you will recognise the input method to set your own rules. Rules must be set using what \R considers to be the 'formula notation'. The rule itself is written *before* the tilde (`~`) and the consequence of the rule is written *after* the tilde:
|
||||
#'
|
||||
#' ```r
|
||||
#' x <- custom_eucast_rules(TZP == "S" ~ aminopenicillins == "S",
|
||||
#' TZP == "R" ~ aminopenicillins == "R")
|
||||
#' x <- custom_interpretive_rules(TZP == "S" ~ aminopenicillins == "S",
|
||||
#' TZP == "R" ~ aminopenicillins == "R")
|
||||
#' ```
|
||||
#'
|
||||
#' These are two custom EUCAST rules: if TZP (piperacillin/tazobactam) is "S", all aminopenicillins (ampicillin and amoxicillin) must be made "S", and if TZP is "R", aminopenicillins must be made "R". These rules can also be printed to the console, so it is immediately clear how they work:
|
||||
#' These are two custom interpretive rules: if TZP (piperacillin/tazobactam) is "S", all aminopenicillins (ampicillin and amoxicillin) must be made "S", and if TZP is "R", aminopenicillins must be made "R". These rules can also be printed to the console, so it is immediately clear how they work:
|
||||
#'
|
||||
#' ```r
|
||||
#' x
|
||||
#' #> A set of custom EUCAST rules:
|
||||
#' #> A set of custom interpretive rules:
|
||||
#' #>
|
||||
#' #> 1. If TZP is "S" then set to S :
|
||||
#' #> amoxicillin (AMX), ampicillin (AMP)
|
||||
@@ -68,11 +68,11 @@
|
||||
#' #> 1 Escherichia coli R S S
|
||||
#' #> 2 Klebsiella pneumoniae R S S
|
||||
#'
|
||||
#' eucast_rules(df,
|
||||
#' rules = "custom",
|
||||
#' custom_rules = x,
|
||||
#' info = FALSE,
|
||||
#' overwrite = TRUE)
|
||||
#' interpretive_rules(df,
|
||||
#' rules = "custom",
|
||||
#' custom_rules = x,
|
||||
#' info = FALSE,
|
||||
#' overwrite = TRUE)
|
||||
#' #> mo TZP ampi cipro
|
||||
#' #> 1 Escherichia coli R R S
|
||||
#' #> 2 Klebsiella pneumoniae R R S
|
||||
@@ -83,16 +83,16 @@
|
||||
#' There is one exception in columns used for the rules: all column names of the [microorganisms] data set can also be used, but do not have to exist in the data set. These column names are: `r vector_and(colnames(microorganisms), sort = FALSE, documentation = TRUE)`. Thus, this next example will work as well, despite the fact that the `df` data set does not contain a column `genus`:
|
||||
#'
|
||||
#' ```r
|
||||
#' y <- custom_eucast_rules(
|
||||
#' y <- custom_interpretive_rules(
|
||||
#' TZP == "S" & genus == "Klebsiella" ~ aminopenicillins == "S",
|
||||
#' TZP == "R" & genus == "Klebsiella" ~ aminopenicillins == "R"
|
||||
#' )
|
||||
#'
|
||||
#' eucast_rules(df,
|
||||
#' rules = "custom",
|
||||
#' custom_rules = y,
|
||||
#' info = FALSE,
|
||||
#' overwrite = TRUE)
|
||||
#' interpretive_rules(df,
|
||||
#' rules = "custom",
|
||||
#' custom_rules = y,
|
||||
#' info = FALSE,
|
||||
#' overwrite = TRUE)
|
||||
#' #> mo TZP ampi cipro
|
||||
#' #> 1 Escherichia coli R S S
|
||||
#' #> 2 Klebsiella pneumoniae R R S
|
||||
@@ -109,9 +109,9 @@
|
||||
#' Rules can also be applied to multiple antimicrobials and antimicrobial groups simultaneously. Use the `c()` function to combine multiple antimicrobials. For instance, the following example sets all aminopenicillins and ureidopenicillins to "R" if column TZP (piperacillin/tazobactam) is "R":
|
||||
#'
|
||||
#' ```r
|
||||
#' x <- custom_eucast_rules(TZP == "R" ~ c(aminopenicillins, ureidopenicillins) == "R")
|
||||
#' x <- custom_interpretive_rules(TZP == "R" ~ c(aminopenicillins, ureidopenicillins) == "R")
|
||||
#' x
|
||||
#' #> A set of custom EUCAST rules:
|
||||
#' #> A set of custom interpretive rules:
|
||||
#' #>
|
||||
#' #> 1. If TZP is "R" then set to "R":
|
||||
#' #> amoxicillin (AMX), ampicillin (AMP), azlocillin (AZL), mezlocillin (MEZ), piperacillin (PIP), piperacillin/tazobactam (TZP)
|
||||
@@ -123,7 +123,7 @@
|
||||
#' @returns A [list] containing the custom rules
|
||||
#' @export
|
||||
#' @examples
|
||||
#' x <- custom_eucast_rules(
|
||||
#' x <- custom_interpretive_rules(
|
||||
#' AMC == "R" & genus == "Klebsiella" ~ aminopenicillins == "R",
|
||||
#' AMC == "I" & genus == "Klebsiella" ~ aminopenicillins == "I"
|
||||
#' )
|
||||
@@ -141,24 +141,24 @@
|
||||
#' # combine rule sets
|
||||
#' x2 <- c(
|
||||
#' x,
|
||||
#' custom_eucast_rules(TZP == "R" ~ carbapenems == "R")
|
||||
#' custom_interpretive_rules(TZP == "R" ~ carbapenems == "R")
|
||||
#' )
|
||||
#' x2
|
||||
custom_eucast_rules <- function(...) {
|
||||
custom_interpretive_rules <- function(...) {
|
||||
dots <- tryCatch(list(...),
|
||||
error = function(e) "error"
|
||||
)
|
||||
stop_if(
|
||||
identical(dots, "error"),
|
||||
"rules must be a valid formula inputs (e.g., using '~'), see {.help [{.fun custom_eucast_rules}](AMR::custom_eucast_rules)}"
|
||||
"rules must be a valid formula inputs (e.g., using '~'), see {.help [{.fun custom_interpretive_rules}](AMR::custom_interpretive_rules)}"
|
||||
)
|
||||
n_dots <- length(dots)
|
||||
stop_if(n_dots == 0, "no custom rules were set. Please read the documentation using {.help [{.fun custom_eucast_rules}](AMR::custom_eucast_rules)}.")
|
||||
stop_if(n_dots == 0, "no custom rules were set. Please read the documentation using {.help [{.fun custom_interpretive_rules}](AMR::custom_interpretive_rules)}.")
|
||||
out <- vector("list", n_dots)
|
||||
for (i in seq_len(n_dots)) {
|
||||
stop_ifnot(
|
||||
inherits(dots[[i]], "formula"),
|
||||
"rule ", i, " must be a valid formula input (e.g., using '~'), see {.help [{.fun custom_eucast_rules}](AMR::custom_eucast_rules)}"
|
||||
"rule ", i, " must be a valid formula input (e.g., using '~'), see {.help [{.fun custom_interpretive_rules}](AMR::custom_interpretive_rules)}"
|
||||
)
|
||||
|
||||
# Query
|
||||
@@ -180,7 +180,7 @@ custom_eucast_rules <- function(...) {
|
||||
result <- dots[[i]][[3]]
|
||||
stop_ifnot(
|
||||
deparse(result) %like% "==",
|
||||
"the result of rule ", i, " (the part after the `~`) must contain `==`, such as in `... ~ ampicillin == \"R\"`, see {.help [{.fun custom_eucast_rules}](AMR::custom_eucast_rules)}"
|
||||
"the result of rule ", i, " (the part after the `~`) must contain `==`, such as in `... ~ ampicillin == \"R\"`, see {.help [{.fun custom_interpretive_rules}](AMR::custom_interpretive_rules)}"
|
||||
)
|
||||
result_group <- as.character(result)[[2]]
|
||||
result_group <- as.character(str2lang(result_group))
|
||||
@@ -230,13 +230,13 @@ custom_eucast_rules <- function(...) {
|
||||
}
|
||||
|
||||
names(out) <- paste0("rule", seq_len(n_dots))
|
||||
set_clean_class(out, new_class = c("custom_eucast_rules", "list"))
|
||||
set_clean_class(out, new_class = c("custom_interpretive_rules", "list"))
|
||||
}
|
||||
|
||||
#' @method c custom_eucast_rules
|
||||
#' @method c custom_interpretive_rules
|
||||
#' @noRd
|
||||
#' @export
|
||||
c.custom_eucast_rules <- function(x, ...) {
|
||||
c.custom_interpretive_rules <- function(x, ...) {
|
||||
if (length(list(...)) == 0) {
|
||||
return(x)
|
||||
}
|
||||
@@ -245,21 +245,21 @@ c.custom_eucast_rules <- function(x, ...) {
|
||||
out <- c(out, unclass(e))
|
||||
}
|
||||
names(out) <- paste0("rule", seq_len(length(out)))
|
||||
set_clean_class(out, new_class = c("custom_eucast_rules", "list"))
|
||||
set_clean_class(out, new_class = c("custom_interpretive_rules", "list"))
|
||||
}
|
||||
|
||||
#' @method as.list custom_eucast_rules
|
||||
#' @method as.list custom_interpretive_rules
|
||||
#' @noRd
|
||||
#' @export
|
||||
as.list.custom_eucast_rules <- function(x, ...) {
|
||||
as.list.custom_interpretive_rules <- function(x, ...) {
|
||||
c(x, ...)
|
||||
}
|
||||
|
||||
#' @method print custom_eucast_rules
|
||||
#' @method print custom_interpretive_rules
|
||||
#' @export
|
||||
#' @noRd
|
||||
print.custom_eucast_rules <- function(x, ...) {
|
||||
cat("A set of custom EUCAST rules:\n")
|
||||
print.custom_interpretive_rules <- function(x, ...) {
|
||||
cat("A set of custom interpretive rules:\n")
|
||||
for (i in seq_len(length(x))) {
|
||||
rule <- x[[i]]
|
||||
rule$query <- format_custom_query_rule(rule$query)
|
||||
@@ -291,3 +291,19 @@ print.custom_eucast_rules <- function(x, ...) {
|
||||
cat("\n ", rule_if, "\n", rule_then, "\n", sep = "")
|
||||
}
|
||||
}
|
||||
|
||||
# Backward-compat S3 dispatch for objects created with the old custom_eucast_rules() function
|
||||
#' @method c custom_eucast_rules
|
||||
#' @noRd
|
||||
#' @export
|
||||
c.custom_eucast_rules <- function(x, ...) c.custom_interpretive_rules(x, ...)
|
||||
|
||||
#' @method as.list custom_eucast_rules
|
||||
#' @noRd
|
||||
#' @export
|
||||
as.list.custom_eucast_rules <- function(x, ...) as.list.custom_interpretive_rules(x, ...)
|
||||
|
||||
#' @method print custom_eucast_rules
|
||||
#' @export
|
||||
#' @noRd
|
||||
print.custom_eucast_rules <- function(x, ...) print.custom_interpretive_rules(x, ...)
|
||||
0
R/first_isolate.R
Normal file → Executable file
0
R/first_isolate.R
Normal file → Executable file
0
R/get_episode.R
Normal file → Executable file
0
R/get_episode.R
Normal file → Executable file
@@ -62,17 +62,17 @@ format_eucast_version_nr <- function(version, markdown = TRUE) {
|
||||
#' @param x A data set with antimicrobials columns, such as `amox`, `AMX` and `AMC`.
|
||||
#' @param info A [logical] to indicate whether progress should be printed to the console - the default is only print while in interactive sessions.
|
||||
#' @param guideline A guideline name, either "EUCAST" (default) or "CLSI". This can be set with the package option [`AMR_guideline`][AMR-options].
|
||||
#' @param rules A [character] vector that specifies which rules should be applied. Must be one or more of `"breakpoints"`, `"expected_phenotypes"`, `"expert"`, `"other"`, `"custom"`, `"all"`, and defaults to `c("breakpoints", "expected_phenotypes")`. The default value can be set to another value using the package option [`AMR_interpretive_rules`][AMR-options]: `options(AMR_interpretive_rules = "all")`. If using `"custom"`, be sure to fill in argument `custom_rules` too. Custom rules can be created with [custom_eucast_rules()].
|
||||
#' @param rules A [character] vector that specifies which rules should be applied. Must be one or more of `"breakpoints"`, `"expected_phenotypes"`, `"expert"`, `"other"`, `"custom"`, `"all"`, and defaults to `c("breakpoints", "expected_phenotypes")`. The default value can be set to another value using the package option [`AMR_interpretive_rules`][AMR-options]: `options(AMR_interpretive_rules = "all")`. If using `"custom"`, be sure to fill in argument `custom_rules` too. Custom rules can be created with [custom_interpretive_rules()].
|
||||
#' @param verbose A [logical] to turn Verbose mode on and off (default is off). In Verbose mode, the function does not apply rules to the data, but instead returns a data set in logbook form with extensive info about which rows and columns would be effected and in which way. Using Verbose mode takes a lot more time.
|
||||
#' @param version_breakpoints The version number to use for the EUCAST Clinical Breakpoints guideline. Can be `r vector_or(names(EUCAST_VERSION_BREAKPOINTS), documentation = TRUE, reverse = TRUE)`.
|
||||
#' @param version_expected_phenotypes The version number to use for the EUCAST Expected Phenotypes. Can be `r vector_or(names(EUCAST_VERSION_EXPECTED_PHENOTYPES), documentation = TRUE, reverse = TRUE)`.
|
||||
#' @param version_expertrules The version number to use for the EUCAST Expert Rules and Intrinsic Resistance guideline. Can be `r vector_or(names(EUCAST_VERSION_EXPERT_RULES), documentation = TRUE, reverse = TRUE)`.
|
||||
#' @param ampc_cephalosporin_resistance (only applies when `rules` contains `"expert"` or `"all"`) a [character] value that should be applied to cefotaxime, ceftriaxone and ceftazidime for AmpC de-repressed cephalosporin-resistant mutants - the default is `NA`. Currently only works when `version_expertrules` is `3.2` and higher; these versions of '*EUCAST Expert Rules on Enterobacterales*' state that results of cefotaxime, ceftriaxone and ceftazidime should be reported with a note, or results should be suppressed (emptied) for these three drugs. A value of `NA` (the default) for this argument will remove results for these three drugs, while e.g. a value of `"R"` will make the results for these drugs resistant. Use `NULL` or `FALSE` to not alter results for these three drugs of AmpC de-repressed cephalosporin-resistant mutants. Using `TRUE` is equal to using `"R"`. \cr For *EUCAST Expert Rules* v3.2, this rule applies to: `r vector_and(gsub("[^a-zA-Z ]+", "", unlist(strsplit(EUCAST_RULES_DF[which(EUCAST_RULES_DF$reference.version %in% c(3.2, 3.3) & EUCAST_RULES_DF$reference.rule %like% "ampc"), "this_value"][1], "|", fixed = TRUE))), quotes = "*")`.
|
||||
#' @param ampc_cephalosporin_resistance (only applies when `rules` contains `"expert"` or `"all"`) a [character] value that should be applied to cefotaxime, ceftriaxone and ceftazidime for AmpC de-repressed cephalosporin-resistant mutants - the default is `NA`. Currently only works when `version_expertrules` is `3.2` and higher; these versions of '*EUCAST Expert Rules on Enterobacterales*' state that results of cefotaxime, ceftriaxone and ceftazidime should be reported with a note, or results should be suppressed (emptied) for these three drugs. A value of `NA` (the default) for this argument will remove results for these three drugs, while e.g. a value of `"R"` will make the results for these drugs resistant. Use `NULL` or `FALSE` to not alter results for these three drugs of AmpC de-repressed cephalosporin-resistant mutants. Using `TRUE` is equal to using `"R"`. \cr For *EUCAST Expert Rules* v3.2, this rule applies to: `r vector_and(gsub("[^a-zA-Z ]+", "", unlist(strsplit(INTERPRETIVE_RULES_DF[which(INTERPRETIVE_RULES_DF$reference.version %in% c(3.2, 3.3) & INTERPRETIVE_RULES_DF$reference.rule %like% "ampc"), "this_value"][1], "|", fixed = TRUE))), quotes = "*")`.
|
||||
#' @param ... Column names of antimicrobials. To automatically detect antimicrobial column names, do not provide any named arguments; [guess_ab_col()] will then be used for detection. To manually specify a column, provide its name (case-insensitive) as an argument, e.g. `AMX = "amoxicillin"`. To skip a specific antimicrobial, set it to `NULL`, e.g. `TIC = NULL` to exclude ticarcillin. If a manually defined column does not exist in the data, it will be skipped with a warning.
|
||||
#' @param ab Any (vector of) text that can be coerced to a valid antimicrobial drug code with [as.ab()].
|
||||
#' @param administration Route of administration, either `r vector_or(dosage$administration, documentation = TRUE)`.
|
||||
#' @param only_sir_columns A [logical] to indicate whether only antimicrobial columns must be included that were transformed to class [sir][as.sir()] on beforehand. Defaults to `FALSE` if no columns of `x` have a class [sir][as.sir()].
|
||||
#' @param custom_rules Custom rules to apply, created with [custom_eucast_rules()].
|
||||
#' @param custom_rules Custom rules to apply, created with [custom_interpretive_rules()].
|
||||
#' @param overwrite A [logical] indicating whether to overwrite existing SIR values (default: `FALSE`). When `FALSE`, only non-SIR values are modified (i.e., any value that is not already S, I or R). To ensure compliance with EUCAST guidelines, **this should remain** `FALSE`, as EUCAST notes often state that an organism "should be tested for susceptibility to individual agents or be reported resistant".
|
||||
#' @param add_if_missing A [logical] indicating whether rules should also be applied to missing (`NA`) values (default: `TRUE`). When `FALSE`, rules are only applied to cells that already contain an SIR value; cells with `NA` are left untouched. This is particularly useful when using `overwrite = TRUE` with custom rules and you want to update reported results without imputing values for untested drugs.
|
||||
#' @inheritParams first_isolate
|
||||
@@ -80,17 +80,17 @@ format_eucast_version_nr <- function(version, markdown = TRUE) {
|
||||
#' **Note:** This function does not translate MIC or disk values to SIR values. Use [as.sir()] for that. \cr
|
||||
#' **Note:** When ampicillin (AMP, J01CA01) is not available but amoxicillin (AMX, J01CA04) is, the latter will be used for all rules where there is a dependency on ampicillin. These drugs are interchangeable when it comes to expression of antimicrobial resistance. \cr
|
||||
#'
|
||||
#' The file containing all EUCAST rules is located here: <https://github.com/msberends/AMR/blob/main/data-raw/eucast_rules.tsv>. **Note:** Old taxonomic names are replaced with the current taxonomy where applicable. For example, *Ochrobactrum anthropi* was renamed to *Brucella anthropi* in 2020; the original EUCAST rules v3.1 and v3.2 did not yet contain this new taxonomic name. The `AMR` package contains the full microbial taxonomy updated until `r documentation_date(max(TAXONOMY_VERSION$GBIF$accessed_date, TAXONOMY_VERSION$LPSN$accessed_date))`, see [microorganisms].
|
||||
#' The file containing all interpretive rules is located here: <https://github.com/msberends/AMR/blob/main/data-raw/interpretive_rules.tsv>. **Note:** Old taxonomic names are replaced with the current taxonomy where applicable. For example, *Ochrobactrum anthropi* was renamed to *Brucella anthropi* in 2020; the original EUCAST rules v3.1 and v3.2 did not yet contain this new taxonomic name. The `AMR` package contains the full microbial taxonomy updated until `r documentation_date(max(TAXONOMY_VERSION$GBIF$accessed_date, TAXONOMY_VERSION$LPSN$accessed_date))`, see [microorganisms].
|
||||
#'
|
||||
#' ### Custom Rules
|
||||
#'
|
||||
#' Custom rules can be created using [custom_eucast_rules()], e.g.:
|
||||
#' Custom rules can be created using [custom_interpretive_rules()], e.g.:
|
||||
#'
|
||||
#' ```r
|
||||
#' x <- custom_eucast_rules(AMC == "R" & genus == "Klebsiella" ~ aminopenicillins == "R",
|
||||
#' AMC == "I" & genus == "Klebsiella" ~ aminopenicillins == "I")
|
||||
#' x <- custom_interpretive_rules(AMC == "R" & genus == "Klebsiella" ~ aminopenicillins == "R",
|
||||
#' AMC == "I" & genus == "Klebsiella" ~ aminopenicillins == "I")
|
||||
#'
|
||||
#' eucast_rules(example_isolates, rules = "custom", custom_rules = x)
|
||||
#' interpretive_rules(example_isolates, rules = "custom", custom_rules = x)
|
||||
#' ```
|
||||
#'
|
||||
#' ### 'Other' Rules
|
||||
@@ -102,7 +102,7 @@ format_eucast_version_nr <- function(version, markdown = TRUE) {
|
||||
#'
|
||||
#' Important examples include amoxicillin and amoxicillin/clavulanic acid, and trimethoprim and trimethoprim/sulfamethoxazole. Needless to say, for these rules to work, both drugs must be available in the data set.
|
||||
#'
|
||||
#' Since these rules are not officially approved by EUCAST, they are not applied at default. To use these rules, include `"other"` to the `rules` argument, or use `eucast_rules(..., rules = "all")`. You can also set the package option [`AMR_interpretive_rules`][AMR-options], i.e. run `options(AMR_interpretive_rules = "all")`.
|
||||
#' Since these rules are not officially approved by EUCAST, they are not applied at default. To use these rules, include `"other"` to the `rules` argument, or use `interpretive_rules(..., rules = "all")`. You can also set the package option [`AMR_interpretive_rules`][AMR-options], i.e. run `options(AMR_interpretive_rules = "all")`.
|
||||
#' @aliases EUCAST
|
||||
#' @rdname interpretive_rules
|
||||
#' @export
|
||||
@@ -184,7 +184,7 @@ interpretive_rules <- function(x,
|
||||
meet_criteria(version_expertrules, allow_class = c("numeric", "integer"), has_length = 1, is_in = as.double(names(EUCAST_VERSION_EXPERT_RULES)))
|
||||
meet_criteria(ampc_cephalosporin_resistance, allow_class = c("logical", "character", "sir"), has_length = 1, allow_NA = TRUE, allow_NULL = TRUE)
|
||||
meet_criteria(only_sir_columns, allow_class = "logical", has_length = 1)
|
||||
meet_criteria(custom_rules, allow_class = "custom_eucast_rules", allow_NULL = TRUE)
|
||||
meet_criteria(custom_rules, allow_class = c("custom_interpretive_rules", "custom_eucast_rules"), allow_NULL = TRUE)
|
||||
meet_criteria(overwrite, allow_class = "logical", has_length = 1)
|
||||
meet_criteria(add_if_missing, allow_class = "logical", has_length = 1)
|
||||
|
||||
@@ -193,11 +193,6 @@ interpretive_rules <- function(x,
|
||||
"Either set {.arg overwrite} or {.arg add_if_missing} to {.code TRUE}, or both."
|
||||
)
|
||||
|
||||
stop_if(
|
||||
guideline == "CLSI",
|
||||
"CLSI guideline is not yet supported."
|
||||
)
|
||||
|
||||
stop_if(
|
||||
!is.na(ampc_cephalosporin_resistance) && !any(c("expert", "all") %in% rules),
|
||||
"For the {.arg ampc_cephalosporin_resistance} argument to work, the {.arg rules} argument must contain {.code \"expert\"} or {.code \"all\"}."
|
||||
@@ -205,8 +200,14 @@ interpretive_rules <- function(x,
|
||||
|
||||
add_MO_lookup_to_AMR_env()
|
||||
|
||||
if (guideline %like% "EUCAST") {
|
||||
guideline <- "EUCAST"
|
||||
} else if (guideline %like% "CLSI") {
|
||||
guideline <- "CLSI"
|
||||
}
|
||||
|
||||
if ("custom" %in% rules && is.null(custom_rules)) {
|
||||
warning_("in {.help [{.fun eucast_rules}](AMR::eucast_rules)}: no custom rules were set with the {.arg custom_rules} argument",
|
||||
warning_("in {.help [{.fun interpretive_rules}](AMR::interpretive_rules)}: no custom rules were set with the {.arg custom_rules} argument",
|
||||
immediate = TRUE
|
||||
)
|
||||
rules <- rules[rules != "custom"]
|
||||
@@ -229,13 +230,13 @@ interpretive_rules <- function(x,
|
||||
|
||||
if (interactive() && isTRUE(verbose) && isTRUE(info)) {
|
||||
txt <- paste0(
|
||||
"WARNING: In Verbose mode, the eucast_rules() function does not apply rules to the data, but instead returns a data set in logbook form with comprehensive info about which rows and columns would be effected and in which way.",
|
||||
"WARNING: In Verbose mode, the interpretive_rules() function does not apply rules to the data, but instead returns a data set in logbook form with comprehensive info about which rows and columns would be effected and in which way.",
|
||||
"\n\nThis may overwrite your existing data if you use e.g.:",
|
||||
"\ndata <- eucast_rules(data, verbose = TRUE)\n\nDo you want to continue?"
|
||||
"\ndata <- interpretive_rules(data, verbose = TRUE)\n\nDo you want to continue?"
|
||||
)
|
||||
showQuestion <- import_fn("showQuestion", "rstudioapi", error_on_fail = FALSE)
|
||||
if (!is.null(showQuestion)) {
|
||||
q_continue <- showQuestion("Using verbose = TRUE with eucast_rules()", txt)
|
||||
q_continue <- showQuestion("Using verbose = TRUE with interpretive_rules()", txt)
|
||||
} else {
|
||||
q_continue <- utils::menu(choices = c("OK", "Cancel"), graphics = FALSE, title = txt)
|
||||
}
|
||||
@@ -330,7 +331,7 @@ interpretive_rules <- function(x,
|
||||
verbose = verbose,
|
||||
info = info,
|
||||
only_sir_columns = only_sir_columns,
|
||||
fn = "eucast_rules",
|
||||
fn = "interpretive_rules",
|
||||
...
|
||||
)
|
||||
|
||||
@@ -489,7 +490,7 @@ interpretive_rules <- function(x,
|
||||
"Rules by the ",
|
||||
font_bold(paste0("AMR package v", utils::packageDescription("AMR")$Version)),
|
||||
" (", format(as.Date(utils::packageDescription("AMR")$Date), format = "%Y"),
|
||||
"), see {.help [{.fun eucast_rules}](AMR::eucast_rules)}\n"
|
||||
"), see {.help [{.fun interpretive_rules}](AMR::interpretive_rules)}\n"
|
||||
)
|
||||
))
|
||||
cat("\n\n")
|
||||
@@ -611,59 +612,62 @@ interpretive_rules <- function(x,
|
||||
|
||||
if (!any(c("all", "custom") %in% rules) && !is.null(custom_rules)) {
|
||||
if (isTRUE(info)) {
|
||||
message_("Skipping custom EUCAST rules, since the {.arg rules} argument does not contain {.code \"custom\"}.")
|
||||
message_("Skipping custom interpretive rules, since the {.arg rules} argument does not contain {.code \"custom\"}.")
|
||||
}
|
||||
custom_rules <- NULL
|
||||
}
|
||||
|
||||
# >>> Apply Official EUCAST rules <<< ---------------------------------------------------
|
||||
# >>> Apply Official interpretive rules <<< ---------------------------------------------------
|
||||
eucast_notification_shown <- FALSE
|
||||
if (!is.null(list(...)$eucast_rules_df)) {
|
||||
# this allows: eucast_rules(x, eucast_rules_df = AMR:::EUCAST_RULES_DF |> filter(is.na(have_these_values)))
|
||||
eucast_rules_df_total <- list(...)$eucast_rules_df
|
||||
if (!is.null(list(...)$interpretive_rules_df)) {
|
||||
# this allows: interpretive_rules(x, interpretive_rules_df = AMR:::INTERPRETIVE_RULES_DF |> filter(is.na(have_these_values)))
|
||||
interpretive_rules_df_total <- list(...)$interpretive_rules_df
|
||||
} else if (!is.null(list(...)$eucast_rules_df)) {
|
||||
# deprecated parameter name kept for backward compatibility
|
||||
interpretive_rules_df_total <- list(...)$eucast_rules_df
|
||||
} else {
|
||||
# otherwise internal data file, created in data-raw/_pre_commit_checks.R
|
||||
eucast_rules_df_total <- EUCAST_RULES_DF
|
||||
# internal data file, created in data-raw/_pre_commit_checks.R
|
||||
interpretive_rules_df_total <- INTERPRETIVE_RULES_DF
|
||||
}
|
||||
|
||||
## filter on user-set guideline versions ----
|
||||
eucast_rules_df <- data.frame()
|
||||
## filter on guideline provider and user-set guideline versions ----
|
||||
interpretive_rules_df <- data.frame()
|
||||
if (any(c("all", "breakpoints") %in% rules)) {
|
||||
eucast_rules_df <- eucast_rules_df %pm>%
|
||||
rbind_AMR(eucast_rules_df_total %pm>%
|
||||
subset(reference.rule_group %like% "breakpoint" & reference.version == version_breakpoints))
|
||||
interpretive_rules_df <- interpretive_rules_df %pm>%
|
||||
rbind_AMR(interpretive_rules_df_total %pm>%
|
||||
subset(rule.provider == guideline & 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))
|
||||
interpretive_rules_df <- interpretive_rules_df %pm>%
|
||||
rbind_AMR(interpretive_rules_df_total %pm>%
|
||||
subset(rule.provider == guideline & 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))
|
||||
interpretive_rules_df <- interpretive_rules_df %pm>%
|
||||
rbind_AMR(interpretive_rules_df_total %pm>%
|
||||
subset(rule.provider == guideline & 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
|
||||
# cefotaxime, ceftriaxone, ceftazidime
|
||||
if (is.null(ampc_cephalosporin_resistance) || isFALSE(ampc_cephalosporin_resistance)) {
|
||||
eucast_rules_df <- subset(
|
||||
eucast_rules_df,
|
||||
interpretive_rules_df <- subset(
|
||||
interpretive_rules_df,
|
||||
reference.rule %unlike% "ampc"
|
||||
)
|
||||
} else {
|
||||
if (isTRUE(ampc_cephalosporin_resistance)) {
|
||||
ampc_cephalosporin_resistance <- "R"
|
||||
}
|
||||
if (!is.null(eucast_rules_df$reference.rule)) {
|
||||
eucast_rules_df[which(eucast_rules_df$reference.rule %like% "ampc"), "to_value"] <- as.character(ampc_cephalosporin_resistance)
|
||||
if (!is.null(interpretive_rules_df$reference.rule)) {
|
||||
interpretive_rules_df[which(interpretive_rules_df$reference.rule %like% "ampc"), "to_value"] <- as.character(ampc_cephalosporin_resistance)
|
||||
}
|
||||
}
|
||||
|
||||
# sometimes, the screenings are missing but the names are actually available
|
||||
# we only hints on remaining rows in `eucast_rules_df`
|
||||
# we only hints on remaining rows in `interpretive_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)], ", *")))]
|
||||
screening_abx <- screening_abx[screening_abx %in% unique(unlist(strsplit(interpretive_rules_df_total$and_these_antibiotics[!is.na(interpretive_rules_df_total$and_these_antibiotics)], ", *")))]
|
||||
if (isTRUE(info)) {
|
||||
cat("\n")
|
||||
}
|
||||
@@ -682,12 +686,12 @@ interpretive_rules <- function(x,
|
||||
}
|
||||
|
||||
## Go over all rules and apply them ----
|
||||
for (i in seq_len(nrow(eucast_rules_df))) {
|
||||
rule_previous <- eucast_rules_df[max(1, i - 1), "reference.rule", drop = TRUE]
|
||||
rule_current <- eucast_rules_df[i, "reference.rule", drop = TRUE]
|
||||
rule_next <- eucast_rules_df[min(nrow(eucast_rules_df), i + 1), "reference.rule", drop = TRUE]
|
||||
rule_group_previous <- eucast_rules_df[max(1, i - 1), "reference.rule_group", drop = TRUE]
|
||||
rule_group_current <- eucast_rules_df[i, "reference.rule_group", drop = TRUE]
|
||||
for (i in seq_len(nrow(interpretive_rules_df))) {
|
||||
rule_previous <- interpretive_rules_df[max(1, i - 1), "reference.rule", drop = TRUE]
|
||||
rule_current <- interpretive_rules_df[i, "reference.rule", drop = TRUE]
|
||||
rule_next <- interpretive_rules_df[min(nrow(interpretive_rules_df), i + 1), "reference.rule", drop = TRUE]
|
||||
rule_group_previous <- interpretive_rules_df[max(1, i - 1), "reference.rule_group", drop = TRUE]
|
||||
rule_group_current <- interpretive_rules_df[i, "reference.rule_group", drop = TRUE]
|
||||
# don't apply rules if user doesn't want to apply them
|
||||
if (rule_group_current %like% "breakpoint" && !any(c("all", "breakpoints") %in% rules)) {
|
||||
next
|
||||
@@ -702,16 +706,16 @@ interpretive_rules <- function(x,
|
||||
if (isFALSE(info) || isFALSE(verbose)) {
|
||||
rule_text <- ""
|
||||
} else {
|
||||
if (is.na(eucast_rules_df[i, "and_these_antibiotics", drop = TRUE])) {
|
||||
rule_text <- paste0("always report as '", eucast_rules_df[i, "to_value", drop = TRUE], "': ", get_antibiotic_names(eucast_rules_df[i, "then_change_these_antibiotics", drop = TRUE]))
|
||||
if (is.na(interpretive_rules_df[i, "and_these_antibiotics", drop = TRUE])) {
|
||||
rule_text <- paste0("always report as '", interpretive_rules_df[i, "to_value", drop = TRUE], "': ", get_antibiotic_names(interpretive_rules_df[i, "then_change_these_antibiotics", drop = TRUE]))
|
||||
} else {
|
||||
rule_text <- paste0(
|
||||
"report as '", eucast_rules_df[i, "to_value", drop = TRUE], "' when ",
|
||||
"report as '", interpretive_rules_df[i, "to_value", drop = TRUE], "' when ",
|
||||
format_antibiotic_names(
|
||||
ab_names = get_antibiotic_names(eucast_rules_df[i, "and_these_antibiotics", drop = TRUE]),
|
||||
ab_results = eucast_rules_df[i, "have_these_values", drop = TRUE]
|
||||
ab_names = get_antibiotic_names(interpretive_rules_df[i, "and_these_antibiotics", drop = TRUE]),
|
||||
ab_results = interpretive_rules_df[i, "have_these_values", drop = TRUE]
|
||||
), ": ",
|
||||
get_antibiotic_names(eucast_rules_df[i, "then_change_these_antibiotics", drop = TRUE])
|
||||
get_antibiotic_names(interpretive_rules_df[i, "then_change_these_antibiotics", drop = TRUE])
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -720,7 +724,7 @@ interpretive_rules <- function(x,
|
||||
rule_previous <- ""
|
||||
rule_group_previous <- ""
|
||||
}
|
||||
if (i == nrow(eucast_rules_df)) {
|
||||
if (i == nrow(interpretive_rules_df)) {
|
||||
rule_next <- ""
|
||||
}
|
||||
|
||||
@@ -789,13 +793,13 @@ interpretive_rules <- function(x,
|
||||
}
|
||||
|
||||
## Get rule from file ------------------------------------------------------
|
||||
if_mo_property <- trimws(eucast_rules_df[i, "if_mo_property", drop = TRUE])
|
||||
like_is_one_of <- trimws(eucast_rules_df[i, "like.is.one_of", drop = TRUE])
|
||||
mo_value <- trimws(eucast_rules_df[i, "this_value", drop = TRUE])
|
||||
source_antibiotics <- eucast_rules_df[i, "and_these_antibiotics", drop = TRUE]
|
||||
source_value <- trimws(unlist(strsplit(eucast_rules_df[i, "have_these_values", drop = TRUE], ",", fixed = TRUE)))
|
||||
target_antibiotics <- eucast_rules_df[i, "then_change_these_antibiotics", drop = TRUE]
|
||||
target_value <- eucast_rules_df[i, "to_value", drop = TRUE]
|
||||
if_mo_property <- trimws(interpretive_rules_df[i, "if_mo_property", drop = TRUE])
|
||||
like_is_one_of <- trimws(interpretive_rules_df[i, "like.is.one_of", drop = TRUE])
|
||||
mo_value <- trimws(interpretive_rules_df[i, "this_value", drop = TRUE])
|
||||
source_antibiotics <- interpretive_rules_df[i, "and_these_antibiotics", drop = TRUE]
|
||||
source_value <- trimws(unlist(strsplit(interpretive_rules_df[i, "have_these_values", drop = TRUE], ",", fixed = TRUE)))
|
||||
target_antibiotics <- interpretive_rules_df[i, "then_change_these_antibiotics", drop = TRUE]
|
||||
target_value <- interpretive_rules_df[i, "to_value", drop = TRUE]
|
||||
|
||||
# if amo_value contains a group name, expand that name with all species in it
|
||||
if (any(trimws(strsplit(mo_value, ",")[[1]]) %in% AMR::microorganisms.groups$mo_group_name, na.rm = TRUE)) {
|
||||
@@ -894,7 +898,7 @@ interpretive_rules <- function(x,
|
||||
if (!is.null(custom_rules)) {
|
||||
if (isTRUE(info)) {
|
||||
cat("\n")
|
||||
cat(font_bold("Custom EUCAST rules, set by user"), "\n")
|
||||
cat(font_bold("Custom interpretive rules, set by user"), "\n")
|
||||
}
|
||||
for (i in seq_len(length(custom_rules))) {
|
||||
rule <- custom_rules[[i]]
|
||||
@@ -929,8 +933,8 @@ interpretive_rules <- function(x,
|
||||
to = target_value,
|
||||
rule = c(
|
||||
rule_text,
|
||||
"Custom EUCAST rules",
|
||||
paste0("Custom EUCAST rule ", i),
|
||||
"Custom interpretive rules",
|
||||
paste0("Custom interpretive rule ", i),
|
||||
paste0(
|
||||
"Object '", deparse(substitute(custom_rules)),
|
||||
"' consisting of ", length(custom_rules), " custom rules"
|
||||
@@ -1075,7 +1079,7 @@ interpretive_rules <- function(x,
|
||||
warn_lacking_sir_class <- warn_lacking_sir_class[order(colnames(x.bak))]
|
||||
warn_lacking_sir_class <- warn_lacking_sir_class[!is.na(warn_lacking_sir_class)]
|
||||
warning_(
|
||||
"in {.help [{.fun eucast_rules}](AMR::eucast_rules)}: not all columns with antimicrobial results are of class {.cls sir}. Transform them on beforehand, e.g.:\n\n",
|
||||
"in {.help [{.fun interpretive_rules}](AMR::interpretive_rules)}: not all columns with antimicrobial results are of class {.cls sir}. Transform them on beforehand, e.g.:\n\n",
|
||||
"\u00a0\u00a0", AMR_env$bullet_icon, " ", highlight_code(paste0(x_deparsed, " |> as.sir(", ifelse(length(warn_lacking_sir_class) == 1,
|
||||
warn_lacking_sir_class,
|
||||
paste0(warn_lacking_sir_class[1], ":", warn_lacking_sir_class[length(warn_lacking_sir_class)])
|
||||
@@ -1177,7 +1181,7 @@ edit_sir <- function(x,
|
||||
new_edits[rows, cols] == "NS")
|
||||
non_SIR <- !isSIR
|
||||
if (isFALSE(overwrite) && any(isSIR) && message_not_thrown_before("edit_sir.warning_overwrite")) {
|
||||
warning_("in {.help [{.fun eucast_rules}](AMR::eucast_rules)}: some columns had SIR values which were not overwritten, since {.code overwrite = FALSE}.")
|
||||
warning_("in {.help [{.fun interpretive_rules}](AMR::interpretive_rules)}: some columns had SIR values which were not overwritten, since {.code overwrite = FALSE}.")
|
||||
}
|
||||
# determine which cells to modify based on overwrite and add_if_missing
|
||||
if (isTRUE(overwrite)) {
|
||||
@@ -1211,7 +1215,7 @@ edit_sir <- function(x,
|
||||
})
|
||||
suppressWarnings(do_assign())
|
||||
warning_(
|
||||
"in {.help [{.fun eucast_rules}](AMR::eucast_rules)}: value \"", to, "\" added to the factor levels of column",
|
||||
"in {.help [{.fun interpretive_rules}](AMR::interpretive_rules)}: value \"", to, "\" added to the factor levels of column",
|
||||
ifelse(length(cols) == 1, "", "s"),
|
||||
" ", vector_and(cols, quotes = "`", sort = FALSE),
|
||||
" because this value was not an existing factor level."
|
||||
@@ -1219,7 +1223,7 @@ edit_sir <- function(x,
|
||||
txt_warning()
|
||||
warned <<- FALSE
|
||||
} else {
|
||||
warning_("in {.help [{.fun eucast_rules}](AMR::eucast_rules)}: ", w$message)
|
||||
warning_("in {.help [{.fun interpretive_rules}](AMR::interpretive_rules)}: ", w$message)
|
||||
txt_warning()
|
||||
}
|
||||
},
|
||||
|
||||
0
R/proportion.R
Normal file → Executable file
0
R/proportion.R
Normal file → Executable file
BIN
R/sysdata.rda
BIN
R/sysdata.rda
Binary file not shown.
0
R/tidymodels.R
Normal file → Executable file
0
R/tidymodels.R
Normal file → Executable file
@@ -70,6 +70,13 @@ as.data.frame.deprecated_amr_dataset <- function(x, ...) {
|
||||
# - `antibiotics` in `antibiogram()`
|
||||
# - `converse_capped_values` in `as.sir()`
|
||||
|
||||
#' @rdname AMR-deprecated
|
||||
#' @export
|
||||
custom_eucast_rules <- function(...) {
|
||||
deprecation_warning("custom_eucast_rules", "custom_interpretive_rules", is_function = TRUE)
|
||||
custom_interpretive_rules(...)
|
||||
}
|
||||
|
||||
#' @rdname AMR-deprecated
|
||||
#' @export
|
||||
ab_class <- function(...) {
|
||||
|
||||
10
_pkgdown.yml
10
_pkgdown.yml
@@ -156,17 +156,17 @@ reference:
|
||||
- "`atc_online_property`"
|
||||
- "`add_custom_antimicrobials`"
|
||||
|
||||
- title: "Preparing data: antimicrobial results"
|
||||
- title: "Interpreting data: antimicrobial results"
|
||||
desc: >
|
||||
With `as.mic()` and `as.disk()` you can transform your raw input to valid MIC or disk diffusion values.
|
||||
Use `as.sir()` for cleaning raw data to let it only contain "R", "I" and "S", or to interpret MIC or disk diffusion values as SIR based on the lastest EUCAST and CLSI guidelines.
|
||||
Afterwards, you can extend antibiotic interpretations by applying [EUCAST rules](https://www.eucast.org/expert_rules_and_intrinsic_resistance/) with `eucast_rules()`.
|
||||
Afterwards, you can extend antibiotic interpretations by applying interpretive rules, for example [from EUCAST](https://www.eucast.org/expert_rules_and_intrinsic_resistance/) with `interpretive_rules()`.
|
||||
contents:
|
||||
- "`as.sir`"
|
||||
- "`as.mic`"
|
||||
- "`as.disk`"
|
||||
- "`eucast_rules`"
|
||||
- "`custom_eucast_rules`"
|
||||
- "`interpretive_rules`"
|
||||
- "`custom_interpretive_rules`"
|
||||
|
||||
- title: "Analysing data"
|
||||
desc: >
|
||||
@@ -265,7 +265,7 @@ reference:
|
||||
|
||||
- title: "Other: statistical tests"
|
||||
desc: >
|
||||
Some statistical tests or methods are not part of base R and were added to this package for convenience.
|
||||
Some statistical tests or methods usable for AMR analyses are not part of base R and were added to this package for convenience.
|
||||
contents:
|
||||
- "`g.test`"
|
||||
- "`kurtosis`"
|
||||
|
||||
@@ -42,9 +42,9 @@ pre_commit_lst <- list()
|
||||
|
||||
usethis::ui_info(paste0("Updating internal package data"))
|
||||
|
||||
# See 'data-raw/eucast_rules.tsv' for the EUCAST reference file
|
||||
pre_commit_lst$EUCAST_RULES_DF <- utils::read.delim(
|
||||
file = "data-raw/eucast_rules.tsv",
|
||||
# See 'data-raw/interpretive_rules.tsv' for the interpretive rules reference file
|
||||
pre_commit_lst$INTERPRETIVE_RULES_DF <- utils::read.delim(
|
||||
file = "data-raw/interpretive_rules.tsv",
|
||||
skip = 9,
|
||||
sep = "\t",
|
||||
stringsAsFactors = FALSE,
|
||||
@@ -364,7 +364,7 @@ pre_commit_lst$MO_RELEVANT_GENERA <- c(
|
||||
)
|
||||
|
||||
# antibiotic groups
|
||||
# (these will also be used for eucast_rules() and understanding data-raw/eucast_rules.tsv)
|
||||
# (these will also be used for interpretive_rules() and understanding data-raw/interpretive_rules.tsv)
|
||||
pre_commit_lst$AB_AMINOGLYCOSIDES <- antimicrobials %>%
|
||||
filter(group %like% "aminoglycoside|paromomycin|spectinomycin") %>%
|
||||
pull(ab)
|
||||
|
||||
1533
data-raw/interpretive_rules.tsv
Normal file
1533
data-raw/interpretive_rules.tsv
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@@ -2,10 +2,13 @@
|
||||
% Please edit documentation in R/zz_deprecated.R
|
||||
\name{AMR-deprecated}
|
||||
\alias{AMR-deprecated}
|
||||
\alias{custom_eucast_rules}
|
||||
\alias{ab_class}
|
||||
\alias{ab_selector}
|
||||
\title{Deprecated Functions, Arguments, or Datasets}
|
||||
\usage{
|
||||
custom_eucast_rules(...)
|
||||
|
||||
ab_class(...)
|
||||
|
||||
ab_selector(...)
|
||||
|
||||
@@ -17,10 +17,10 @@ age_groups(x, split_at = c(0, 12, 25, 55, 75), names = NULL,
|
||||
\item{na.rm}{A \link{logical} to indicate whether missing values should be removed.}
|
||||
}
|
||||
\value{
|
||||
Ordered \link{factor}
|
||||
Ordered [factor]
|
||||
}
|
||||
\description{
|
||||
Split ages into age groups defined by the \code{split} argument. This allows for easier demographic (antimicrobial resistance) analysis. The function returns an ordered \link{factor}.
|
||||
Split ages into age groups defined by the `split` argument. This allows for easier demographic (antimicrobial resistance) analysis. The function returns an ordered [factor].
|
||||
}
|
||||
\details{
|
||||
To split ages, the input for the \code{split_at} argument can be:
|
||||
|
||||
@@ -30,26 +30,6 @@ step_mic_log2(recipe, ..., role = NA, trained = FALSE, columns = NULL,
|
||||
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{<sir>} and \verb{<mic>} inside \code{tidymodels} pipelines.
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ antibiogram(x, antimicrobials = where(is.sir), mo_transform = "shortname",
|
||||
ifelse(wisca, 14, 18)), col_mo = NULL, language = get_AMR_locale(),
|
||||
minimum = 30, combine_SI = TRUE, sep = " + ", sort_columns = TRUE,
|
||||
wisca = FALSE, simulations = 1000, conf_interval = 0.95,
|
||||
interval_side = "two-tailed", info = interactive(), ...)
|
||||
interval_side = "two-tailed", info = interactive(), parallel = FALSE,
|
||||
...)
|
||||
|
||||
wisca(x, antimicrobials = where(is.sir), ab_transform = "name",
|
||||
syndromic_group = NULL, only_all_tested = FALSE, digits = 1,
|
||||
@@ -33,7 +34,7 @@ wisca(x, antimicrobials = where(is.sir), ab_transform = "name",
|
||||
col_mo = NULL, language = get_AMR_locale(), combine_SI = TRUE,
|
||||
sep = " + ", sort_columns = TRUE, simulations = 1000,
|
||||
conf_interval = 0.95, interval_side = "two-tailed",
|
||||
info = interactive(), ...)
|
||||
info = interactive(), parallel = FALSE, ...)
|
||||
|
||||
retrieve_wisca_parameters(wisca_model, ...)
|
||||
|
||||
@@ -72,7 +73,7 @@ retrieve_wisca_parameters(wisca_model, ...)
|
||||
|
||||
\item{ab_transform}{A character to transform antimicrobial input - must be one of the column names of the \link{antimicrobials} data set (defaults to \code{"name"}): \code{"ab"}, \code{"cid"}, \code{"name"}, \code{"group"}, \code{"atc"}, \code{"atc_group1"}, \code{"atc_group2"}, \code{"abbreviations"}, \code{"synonyms"}, \code{"oral_ddd"}, \code{"oral_units"}, \code{"iv_ddd"}, \code{"iv_units"}, or \code{"loinc"}. Can also be \code{NULL} to not transform the input.}
|
||||
|
||||
\item{syndromic_group}{A column name of \code{x}, or values calculated to split rows of \code{x}, e.g. by using \code{\link[=ifelse]{ifelse()}} or \code{\link[dplyr:case-and-replace-when]{case_when()}}. See \emph{Examples}.}
|
||||
\item{syndromic_group}{A column name of `x`, or values calculated to split rows of `x`, e.g. by using [ifelse()] or [`case_when()`][dplyr::case_when()]. See *Examples*.}
|
||||
|
||||
\item{add_total_n}{\emph{(deprecated in favour of \code{formatting_type})} A \link{logical} to indicate whether \code{n_tested} available numbers per pathogen should be added to the table (default is \code{TRUE}). This will add the lowest and highest number of available isolates per antimicrobial (e.g, if for \emph{E. coli} 200 isolates are available for ciprofloxacin and 150 for amoxicillin, the returned number will be "150-200"). This option is unavailable when \code{wisca = TRUE}; in that case, use \code{\link[=retrieve_wisca_parameters]{retrieve_wisca_parameters()}} to get the parameters used for WISCA.}
|
||||
|
||||
@@ -80,7 +81,7 @@ retrieve_wisca_parameters(wisca_model, ...)
|
||||
|
||||
\item{digits}{Number of digits to use for rounding the antimicrobial coverage, defaults to 1 for WISCA and 0 otherwise.}
|
||||
|
||||
\item{formatting_type}{Numeric value (1–22 for WISCA, 1-12 for non-WISCA) indicating how the 'cells' of the antibiogram table should be formatted. See \emph{Details} > \emph{Formatting Type} for a list of options.}
|
||||
\item{formatting_type}{Numeric value (1-22 for WISCA, 1-12 for non-WISCA) indicating how the 'cells' of the antibiogram table should be formatted. See \emph{Details} > \emph{Formatting Type} for a list of options.}
|
||||
|
||||
\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()}}.}
|
||||
|
||||
@@ -104,6 +105,8 @@ retrieve_wisca_parameters(wisca_model, ...)
|
||||
|
||||
\item{info}{A \link{logical} to indicate info should be printed - the default is \code{TRUE} only in interactive mode.}
|
||||
|
||||
\item{parallel}{A \link{logical} to indicate if parallel computing must be used, defaults to \code{FALSE}. Requires the \code{\link[future.apply:future_lapply]{future.apply}} package. For WISCA, Monte Carlo simulations are distributed across workers; for grouped antibiograms, each group is processed by a separate worker. \strong{A non-sequential \code{\link[future:plan]{future::plan()}} must already be active before setting \code{parallel = TRUE}} -- for example, \code{future::plan(future::multisession)}. An error is thrown if \code{parallel = TRUE} is used without a plan set by the user.}
|
||||
|
||||
\item{...}{When used in \link[knitr:kable]{R Markdown or Quarto}: arguments passed on to \code{\link[knitr:kable]{knitr::kable()}} (otherwise, has no use).}
|
||||
|
||||
\item{wisca_model}{The outcome of \code{\link[=wisca]{wisca()}} or \code{\link[=antibiogram]{antibiogram(..., wisca = TRUE)}}.}
|
||||
|
||||
@@ -39,22 +39,23 @@ mic_p90(x, na.rm = FALSE, ...)
|
||||
|
||||
\item{mic_range}{A manual range to rescale the MIC values, e.g., \code{mic_range = c(0.001, 32)}. Use \code{NA} to prevent rescaling on one side, e.g., \code{mic_range = c(NA, 32)}.}
|
||||
|
||||
\item{as.mic}{A \link{logical} to indicate whether the \code{mic} class should be kept - the default is \code{TRUE} for \code{\link[=rescale_mic]{rescale_mic()}} and \code{FALSE} for \code{\link[=droplevels]{droplevels()}}. When setting this to \code{FALSE} in \code{\link[=rescale_mic]{rescale_mic()}}, the output will have factor levels that acknowledge \code{mic_range}.}
|
||||
\item{as.mic}{A [logical] to indicate whether the `mic` class should be kept - the default is `TRUE` for [rescale_mic()] and `FALSE` for [droplevels()]. When setting this to `FALSE` in [rescale_mic()], the output will have factor levels that acknowledge `mic_range`.}
|
||||
|
||||
\item{...}{Arguments passed on to methods.}
|
||||
}
|
||||
\value{
|
||||
Ordered \link{factor} with additional class \code{\link{mic}}, that in mathematical operations acts as a \link{numeric} vector. Bear in mind that the outcome of any mathematical operation on MICs will return a \link{numeric} value.
|
||||
Ordered [factor] with additional class [`mic`], that in mathematical operations acts as a [numeric] vector. Bear in mind that the outcome of any mathematical operation on MICs will return a [numeric] value.
|
||||
}
|
||||
\description{
|
||||
This transforms vectors to a new class \code{\link{mic}}, which treats the input as decimal numbers, while maintaining operators (such as ">=") and only allowing valid MIC values known to the field of (medical) microbiology.
|
||||
}
|
||||
\details{
|
||||
To interpret MIC values as SIR values, use \code{\link[=as.sir]{as.sir()}} on MIC values. It supports guidelines from EUCAST (2011-2026) and CLSI (2011-2026).
|
||||
To interpret MIC values as SIR values, use [as.sir()] on MIC values. It supports guidelines from EUCAST (`r min(as.integer(gsub("[^0-9]", "", subset(clinical_breakpoints, guideline %like% "EUCAST")$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(clinical_breakpoints, guideline %like% "EUCAST")$guideline)))`) and CLSI (`r min(as.integer(gsub("[^0-9]", "", subset(clinical_breakpoints, guideline %like% "CLSI")$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(clinical_breakpoints, guideline %like% "CLSI")$guideline)))`).
|
||||
|
||||
This class for MIC values is a quite a special data type: formally it is an ordered \link{factor} with valid MIC values as \link{factor} levels (to make sure only valid MIC values are retained), but for any mathematical operation it acts as decimal numbers:
|
||||
This class for MIC values is a quite a special data type: formally it is an ordered [factor] with valid MIC values as [factor] levels (to make sure only valid MIC values are retained), but for any mathematical operation it acts as decimal numbers:
|
||||
|
||||
\if{html}{\out{<div class="sourceCode">}}\preformatted{x <- random_mic(10)
|
||||
```
|
||||
x <- random_mic(10)
|
||||
x
|
||||
#> Class <mic>
|
||||
#> [1] 16 1 8 8 64 >=128 0.0625 32 32 16
|
||||
@@ -67,16 +68,17 @@ x[1] * 2
|
||||
|
||||
median(x)
|
||||
#> [1] 26
|
||||
}\if{html}{\out{</div>}}
|
||||
```
|
||||
|
||||
This makes it possible to maintain operators that often come with MIC values, such ">=" and "<=", even when filtering using \link{numeric} values in data analysis, e.g.:
|
||||
This makes it possible to maintain operators that often come with MIC values, such ">=" and "<=", even when filtering using [numeric] values in data analysis, e.g.:
|
||||
|
||||
\if{html}{\out{<div class="sourceCode">}}\preformatted{x[x > 4]
|
||||
```
|
||||
x[x > 4]
|
||||
#> Class <mic>
|
||||
#> [1] 16 8 8 64 >=128 32 32 16
|
||||
|
||||
df <- data.frame(x, hospital = "A")
|
||||
subset(df, x > 4) # or with dplyr: df \%>\% filter(x > 4)
|
||||
subset(df, x > 4) # or with dplyr: df %>% filter(x > 4)
|
||||
#> x hospital
|
||||
#> 1 16 A
|
||||
#> 5 64 A
|
||||
@@ -84,19 +86,19 @@ subset(df, x > 4) # or with dplyr: df \%>\% filter(x > 4)
|
||||
#> 8 32 A
|
||||
#> 9 32 A
|
||||
#> 10 16 A
|
||||
}\if{html}{\out{</div>}}
|
||||
```
|
||||
|
||||
All so-called \link[=groupGeneric]{group generic functions} are implemented for the MIC class (such as \code{!}, \code{!=}, \code{<}, \code{>=}, \code{\link[=exp]{exp()}}, \code{\link[=log2]{log2()}}). Some mathematical functions are also implemented (such as \code{\link[=quantile]{quantile()}}, \code{\link[=median]{median()}}, \code{\link[=fivenum]{fivenum()}}). Since \code{\link[=sd]{sd()}} and \code{\link[=var]{var()}} are non-generic functions, these could not be extended. Use \code{\link[=mad]{mad()}} as an alternative, or use e.g. \code{sd(as.numeric(x))} where \code{x} is your vector of MIC values.
|
||||
All so-called [group generic functions][groupGeneric()] are implemented for the MIC class (such as `!`, `!=`, `<`, `>=`, [exp()], [log2()]). Some mathematical functions are also implemented (such as [quantile()], [median()], [fivenum()]). Since [sd()] and [var()] are non-generic functions, these could not be extended. Use [mad()] as an alternative, or use e.g. `sd(as.numeric(x))` where `x` is your vector of MIC values.
|
||||
|
||||
Using \code{\link[=as.double]{as.double()}} or \code{\link[=as.numeric]{as.numeric()}} on MIC values will remove the operators and return a numeric vector. Do \strong{not} use \code{\link[=as.integer]{as.integer()}} on MIC values as by the \R convention on \link{factor}s, it will return the index of the factor levels (which is often useless for regular users).
|
||||
Using [as.double()] or [as.numeric()] on MIC values will remove the operators and return a numeric vector. Do **not** use [as.integer()] on MIC values as by the \R convention on [factor]s, it will return the index of the factor levels (which is often useless for regular users).
|
||||
|
||||
The function \code{\link[=is.mic]{is.mic()}} detects if the input contains class \code{mic}. If the input is a \link{data.frame} or \link{list}, it iterates over all columns/items and returns a \link{logical} vector.
|
||||
The function [is.mic()] detects if the input contains class `mic`. If the input is a [data.frame] or [list], it iterates over all columns/items and returns a [logical] vector.
|
||||
|
||||
Use \code{\link[=droplevels]{droplevels()}} to drop unused levels. At default, it will return a plain factor. Use \code{droplevels(..., as.mic = TRUE)} to maintain the \code{mic} class.
|
||||
Use [droplevels()] to drop unused levels. At default, it will return a plain factor. Use `droplevels(..., as.mic = TRUE)` to maintain the `mic` class.
|
||||
|
||||
With \code{\link[=rescale_mic]{rescale_mic()}}, existing MIC ranges can be limited to a defined range of MIC values. This can be useful to better compare MIC distributions.
|
||||
With [rescale_mic()], existing MIC ranges can be limited to a defined range of MIC values. This can be useful to better compare MIC distributions.
|
||||
|
||||
For \code{ggplot2}, use one of the \code{\link[=scale_x_mic]{scale_*_mic()}} functions to plot MIC values. They allows custom MIC ranges and to plot intermediate log2 levels for missing MIC values.
|
||||
For `ggplot2`, use one of the [`scale_*_mic()`][scale_x_mic()] functions to plot MIC values. They allows custom MIC ranges and to plot intermediate log2 levels for missing MIC values.
|
||||
|
||||
\code{NA_mic_} is a missing value of the new \code{mic} class, analogous to e.g. base \R's \code{\link[base:NA]{NA_character_}}.
|
||||
|
||||
|
||||
@@ -155,12 +155,12 @@ The default \code{"conservative"} setting ensures cautious handling of uncertain
|
||||
\item{clean}{A \link{logical} to indicate whether previously stored results should be forgotten after returning the 'logbook' with results.}
|
||||
}
|
||||
\value{
|
||||
Ordered \link{factor} with new class \code{sir}
|
||||
Ordered [factor] with new class `sir`
|
||||
}
|
||||
\description{
|
||||
Clean up existing SIR values, or interpret minimum inhibitory concentration (MIC) values and disk diffusion diameters according to EUCAST or CLSI. \code{\link[=as.sir]{as.sir()}} transforms the input to a new class \code{\link{sir}}, which is an ordered \link{factor} containing the levels \code{S}, \code{SDD}, \code{I}, \code{R}, \code{NI}.
|
||||
Clean up existing SIR values, or interpret minimum inhibitory concentration (MIC) values and disk diffusion diameters according to EUCAST or CLSI. [as.sir()] transforms the input to a new class [`sir`], which is an ordered [factor] containing the levels `S`, `SDD`, `I`, `R`, `NI`.
|
||||
|
||||
Breakpoints are currently implemented from EUCAST 2011-2026 and CLSI 2011-2026, see \emph{Details}. All breakpoints used for interpretation are available in our \link{clinical_breakpoints} data set.
|
||||
Breakpoints are currently implemented from EUCAST `r min(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, guideline %like% "EUCAST")$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, guideline %like% "EUCAST")$guideline)))` and CLSI `r min(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, guideline %like% "CLSI")$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, guideline %like% "CLSI")$guideline)))`, see *Details*. All breakpoints used for interpretation are available in our [clinical_breakpoints] data set.
|
||||
}
|
||||
\details{
|
||||
\emph{Note: The clinical breakpoints in this package were validated through, and imported from, \href{https://whonet.org}{WHONET}. The public use of this \code{AMR} package has been endorsed by both CLSI and EUCAST. See \link{clinical_breakpoints} for more information.}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/custom_eucast_rules.R
|
||||
\name{custom_eucast_rules}
|
||||
\alias{custom_eucast_rules}
|
||||
\title{Define Custom EUCAST Rules}
|
||||
% Please edit documentation in R/custom_interpretive_rules.R
|
||||
\name{custom_interpretive_rules}
|
||||
\alias{custom_interpretive_rules}
|
||||
\title{Define Custom Interpretive Rules}
|
||||
\usage{
|
||||
custom_eucast_rules(...)
|
||||
custom_interpretive_rules(...)
|
||||
}
|
||||
\arguments{
|
||||
\item{...}{Rules in \link[base:tilde]{formula} notation, see below for instructions, and in \emph{Examples}.}
|
||||
@@ -13,22 +13,22 @@ custom_eucast_rules(...)
|
||||
A \link{list} containing the custom rules
|
||||
}
|
||||
\description{
|
||||
Define custom EUCAST rules for your organisation or specific analysis and use the output of this function in \code{\link[=eucast_rules]{eucast_rules()}}.
|
||||
Define custom interpretive rules for your organisation or specific analysis and use the output of this function in \code{\link[=interpretive_rules]{interpretive_rules()}}.
|
||||
}
|
||||
\details{
|
||||
Some organisations have their own adoption of EUCAST rules. This function can be used to define custom EUCAST rules to be used in the \code{\link[=eucast_rules]{eucast_rules()}} function.
|
||||
Some organisations have their own adoption of interpretive rules. This function can be used to define custom rules to be used in the \code{\link[=interpretive_rules]{interpretive_rules()}} function.
|
||||
\subsection{Basics}{
|
||||
|
||||
If you are familiar with the \code{\link[dplyr:case-and-replace-when]{case_when()}} function of the \code{dplyr} package, you will recognise the input method to set your own rules. Rules must be set using what \R considers to be the 'formula notation'. The rule itself is written \emph{before} the tilde (\code{~}) and the consequence of the rule is written \emph{after} the tilde:
|
||||
|
||||
\if{html}{\out{<div class="sourceCode r">}}\preformatted{x <- custom_eucast_rules(TZP == "S" ~ aminopenicillins == "S",
|
||||
TZP == "R" ~ aminopenicillins == "R")
|
||||
\if{html}{\out{<div class="sourceCode r">}}\preformatted{x <- custom_interpretive_rules(TZP == "S" ~ aminopenicillins == "S",
|
||||
TZP == "R" ~ aminopenicillins == "R")
|
||||
}\if{html}{\out{</div>}}
|
||||
|
||||
These are two custom EUCAST rules: if TZP (piperacillin/tazobactam) is "S", all aminopenicillins (ampicillin and amoxicillin) must be made "S", and if TZP is "R", aminopenicillins must be made "R". These rules can also be printed to the console, so it is immediately clear how they work:
|
||||
These are two custom interpretive rules: if TZP (piperacillin/tazobactam) is "S", all aminopenicillins (ampicillin and amoxicillin) must be made "S", and if TZP is "R", aminopenicillins must be made "R". These rules can also be printed to the console, so it is immediately clear how they work:
|
||||
|
||||
\if{html}{\out{<div class="sourceCode r">}}\preformatted{x
|
||||
#> A set of custom EUCAST rules:
|
||||
#> A set of custom interpretive rules:
|
||||
#>
|
||||
#> 1. If TZP is "S" then set to S :
|
||||
#> amoxicillin (AMX), ampicillin (AMP)
|
||||
@@ -48,11 +48,11 @@ df
|
||||
#> 1 Escherichia coli R S S
|
||||
#> 2 Klebsiella pneumoniae R S S
|
||||
|
||||
eucast_rules(df,
|
||||
rules = "custom",
|
||||
custom_rules = x,
|
||||
info = FALSE,
|
||||
overwrite = TRUE)
|
||||
interpretive_rules(df,
|
||||
rules = "custom",
|
||||
custom_rules = x,
|
||||
info = FALSE,
|
||||
overwrite = TRUE)
|
||||
#> mo TZP ampi cipro
|
||||
#> 1 Escherichia coli R R S
|
||||
#> 2 Klebsiella pneumoniae R R S
|
||||
@@ -63,16 +63,16 @@ eucast_rules(df,
|
||||
|
||||
There is one exception in columns used for the rules: all column names of the \link{microorganisms} data set can also be used, but do not have to exist in the data set. These column names are: \code{"mo"}, \code{"fullname"}, \code{"status"}, \code{"kingdom"}, \code{"phylum"}, \code{"class"}, \code{"order"}, \code{"family"}, \code{"genus"}, \code{"species"}, \code{"subspecies"}, \code{"rank"}, \code{"ref"}, \code{"oxygen_tolerance"}, \code{"source"}, \code{"lpsn"}, \code{"lpsn_parent"}, \code{"lpsn_renamed_to"}, \code{"mycobank"}, \code{"mycobank_parent"}, \code{"mycobank_renamed_to"}, \code{"gbif"}, \code{"gbif_parent"}, \code{"gbif_renamed_to"}, \code{"prevalence"}, and \code{"snomed"}. Thus, this next example will work as well, despite the fact that the \code{df} data set does not contain a column \code{genus}:
|
||||
|
||||
\if{html}{\out{<div class="sourceCode r">}}\preformatted{y <- custom_eucast_rules(
|
||||
\if{html}{\out{<div class="sourceCode r">}}\preformatted{y <- custom_interpretive_rules(
|
||||
TZP == "S" & genus == "Klebsiella" ~ aminopenicillins == "S",
|
||||
TZP == "R" & genus == "Klebsiella" ~ aminopenicillins == "R"
|
||||
)
|
||||
|
||||
eucast_rules(df,
|
||||
rules = "custom",
|
||||
custom_rules = y,
|
||||
info = FALSE,
|
||||
overwrite = TRUE)
|
||||
interpretive_rules(df,
|
||||
rules = "custom",
|
||||
custom_rules = y,
|
||||
info = FALSE,
|
||||
overwrite = TRUE)
|
||||
#> mo TZP ampi cipro
|
||||
#> 1 Escherichia coli R S S
|
||||
#> 2 Klebsiella pneumoniae R R S
|
||||
@@ -90,9 +90,9 @@ You can define antimicrobial groups instead of single antimicrobials for the rul
|
||||
|
||||
Rules can also be applied to multiple antimicrobials and antimicrobial groups simultaneously. Use the \code{c()} function to combine multiple antimicrobials. For instance, the following example sets all aminopenicillins and ureidopenicillins to "R" if column TZP (piperacillin/tazobactam) is "R":
|
||||
|
||||
\if{html}{\out{<div class="sourceCode r">}}\preformatted{x <- custom_eucast_rules(TZP == "R" ~ c(aminopenicillins, ureidopenicillins) == "R")
|
||||
\if{html}{\out{<div class="sourceCode r">}}\preformatted{x <- custom_interpretive_rules(TZP == "R" ~ c(aminopenicillins, ureidopenicillins) == "R")
|
||||
x
|
||||
#> A set of custom EUCAST rules:
|
||||
#> A set of custom interpretive rules:
|
||||
#>
|
||||
#> 1. If TZP is "R" then set to "R":
|
||||
#> amoxicillin (AMX), ampicillin (AMP), azlocillin (AZL), mezlocillin (MEZ), piperacillin (PIP), piperacillin/tazobactam (TZP)
|
||||
@@ -147,7 +147,7 @@ These 43 antimicrobial groups are allowed in the rules (case-insensitive) and ca
|
||||
}
|
||||
}
|
||||
\examples{
|
||||
x <- custom_eucast_rules(
|
||||
x <- custom_interpretive_rules(
|
||||
AMC == "R" & genus == "Klebsiella" ~ aminopenicillins == "R",
|
||||
AMC == "I" & genus == "Klebsiella" ~ aminopenicillins == "I"
|
||||
)
|
||||
@@ -165,7 +165,7 @@ eucast_rules(example_isolates,
|
||||
# combine rule sets
|
||||
x2 <- c(
|
||||
x,
|
||||
custom_eucast_rules(TZP == "R" ~ carbapenems == "R")
|
||||
custom_interpretive_rules(TZP == "R" ~ carbapenems == "R")
|
||||
)
|
||||
x2
|
||||
}
|
||||
@@ -12,7 +12,7 @@ custom_mdro_guideline(..., as_factor = TRUE)
|
||||
\arguments{
|
||||
\item{...}{Guideline rules in \link[base:tilde]{formula} notation, see below for instructions, and in \emph{Examples}.}
|
||||
|
||||
\item{as_factor}{A \link{logical} to indicate whether the returned value should be an ordered \link{factor} (\code{TRUE}, default), or otherwise a \link{character} vector. For combining rules sets (using \code{\link[=c]{c()}}) this value will be inherited from the first set at default.}
|
||||
\item{as_factor}{A [logical] to indicate whether the returned value should be an ordered [factor] (`TRUE`, default), or otherwise a [character] vector. For combining rules sets (using [c()]) this value will be inherited from the first set at default.}
|
||||
|
||||
\item{x}{Existing custom MDRO rules}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ A list with class \code{"htest"} containing the following
|
||||
\code{(observed - expected) / sqrt(expected)}.}
|
||||
\item{stdres}{standardized residuals,
|
||||
\code{(observed - expected) / sqrt(V)}, where \code{V} is the
|
||||
residual cell variance (Agresti, 2007, section 2.4.5
|
||||
residual cell variance {(\if{html}{\out{<a href="#reference+chisq.test.Rd+R+3AAgresti+3A2007" class="citation">}}Agresti 2007\if{html}{\out{</a>}}, section 2.4.5)}
|
||||
for the case where \code{x} is a matrix, \code{n * p * (1 - p)} otherwise).}
|
||||
}
|
||||
\description{
|
||||
|
||||
@@ -42,8 +42,9 @@ ggplot_pca(x, choices = 1:2, scale = 1, pc.biplot = TRUE,
|
||||
}
|
||||
|
||||
\item{pc.biplot}{
|
||||
If true, use what Gabriel (1971) refers to as a "principal component
|
||||
biplot", with \code{lambda = 1} and observations scaled up by sqrt(n) and
|
||||
If true, use what {\if{html}{\cite{}\out{<a href="#reference+biplot.princomp.Rd+R+3AGabriel+3A1971" class="citation">}}Gabriel (1971)\if{html}{\out{</a>}}} refers to as a
|
||||
\dQuote{principal component biplot},
|
||||
with \code{lambda = 1} and observations scaled up by sqrt(n) and
|
||||
variables scaled down by sqrt(n). Then inner products between
|
||||
variables approximate covariances and distances between observations
|
||||
approximate Mahalanobis distance.
|
||||
|
||||
@@ -46,7 +46,7 @@ eucast_dosage(ab, administration = "iv", version_breakpoints = 15)
|
||||
|
||||
\item{info}{A \link{logical} to indicate whether progress should be printed to the console - the default is only print while in interactive sessions.}
|
||||
|
||||
\item{rules}{A \link{character} vector that specifies which rules should be applied. Must be one or more of \code{"breakpoints"}, \code{"expected_phenotypes"}, \code{"expert"}, \code{"other"}, \code{"custom"}, \code{"all"}, and defaults to \code{c("breakpoints", "expected_phenotypes")}. The default value can be set to another value using the package option \code{\link[=AMR-options]{AMR_interpretive_rules}}: \code{options(AMR_interpretive_rules = "all")}. If using \code{"custom"}, be sure to fill in argument \code{custom_rules} too. Custom rules can be created with \code{\link[=custom_eucast_rules]{custom_eucast_rules()}}.}
|
||||
\item{rules}{A \link{character} vector that specifies which rules should be applied. Must be one or more of \code{"breakpoints"}, \code{"expected_phenotypes"}, \code{"expert"}, \code{"other"}, \code{"custom"}, \code{"all"}, and defaults to \code{c("breakpoints", "expected_phenotypes")}. The default value can be set to another value using the package option \code{\link[=AMR-options]{AMR_interpretive_rules}}: \code{options(AMR_interpretive_rules = "all")}. If using \code{"custom"}, be sure to fill in argument \code{custom_rules} too. Custom rules can be created with \code{\link[=custom_interpretive_rules]{custom_interpretive_rules()}}.}
|
||||
|
||||
\item{guideline}{A guideline name, either "EUCAST" (default) or "CLSI". This can be set with the package option \code{\link[=AMR-options]{AMR_guideline}}.}
|
||||
|
||||
@@ -62,7 +62,7 @@ eucast_dosage(ab, administration = "iv", version_breakpoints = 15)
|
||||
|
||||
\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{custom_rules}{Custom rules to apply, created with \code{\link[=custom_eucast_rules]{custom_eucast_rules()}}.}
|
||||
\item{custom_rules}{Custom rules to apply, created with \code{\link[=custom_interpretive_rules]{custom_interpretive_rules()}}.}
|
||||
|
||||
\item{overwrite}{A \link{logical} indicating whether to overwrite existing SIR values (default: \code{FALSE}). When \code{FALSE}, only non-SIR values are modified (i.e., any value that is not already S, I or R). To ensure compliance with EUCAST guidelines, \strong{this should remain} \code{FALSE}, as EUCAST notes often state that an organism "should be tested for susceptibility to individual agents or be reported resistant".}
|
||||
|
||||
@@ -86,15 +86,15 @@ To improve the interpretation of the antibiogram before CLSI/EUCAST interpretive
|
||||
\strong{Note:} This function does not translate MIC or disk values to SIR values. Use \code{\link[=as.sir]{as.sir()}} for that. \cr
|
||||
\strong{Note:} When ampicillin (AMP, J01CA01) is not available but amoxicillin (AMX, J01CA04) is, the latter will be used for all rules where there is a dependency on ampicillin. These drugs are interchangeable when it comes to expression of antimicrobial resistance. \cr
|
||||
|
||||
The file containing all EUCAST rules is located here: \url{https://github.com/msberends/AMR/blob/main/data-raw/eucast_rules.tsv}. \strong{Note:} Old taxonomic names are replaced with the current taxonomy where applicable. For example, \emph{Ochrobactrum anthropi} was renamed to \emph{Brucella anthropi} in 2020; the original EUCAST rules v3.1 and v3.2 did not yet contain this new taxonomic name. The \code{AMR} package contains the full microbial taxonomy updated until June 24th, 2024, see \link{microorganisms}.
|
||||
The file containing all interpretive rules is located here: \url{https://github.com/msberends/AMR/blob/main/data-raw/interpretive_rules.tsv}. \strong{Note:} Old taxonomic names are replaced with the current taxonomy where applicable. For example, \emph{Ochrobactrum anthropi} was renamed to \emph{Brucella anthropi} in 2020; the original EUCAST rules v3.1 and v3.2 did not yet contain this new taxonomic name. The \code{AMR} package contains the full microbial taxonomy updated until June 24th, 2024, see \link{microorganisms}.
|
||||
\subsection{Custom Rules}{
|
||||
|
||||
Custom rules can be created using \code{\link[=custom_eucast_rules]{custom_eucast_rules()}}, e.g.:
|
||||
Custom rules can be created using \code{\link[=custom_interpretive_rules]{custom_interpretive_rules()}}, e.g.:
|
||||
|
||||
\if{html}{\out{<div class="sourceCode r">}}\preformatted{x <- custom_eucast_rules(AMC == "R" & genus == "Klebsiella" ~ aminopenicillins == "R",
|
||||
AMC == "I" & genus == "Klebsiella" ~ aminopenicillins == "I")
|
||||
\if{html}{\out{<div class="sourceCode r">}}\preformatted{x <- custom_interpretive_rules(AMC == "R" & genus == "Klebsiella" ~ aminopenicillins == "R",
|
||||
AMC == "I" & genus == "Klebsiella" ~ aminopenicillins == "I")
|
||||
|
||||
eucast_rules(example_isolates, rules = "custom", custom_rules = x)
|
||||
interpretive_rules(example_isolates, rules = "custom", custom_rules = x)
|
||||
}\if{html}{\out{</div>}}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ Before further processing, two non-EUCAST rules about drug combinations can be a
|
||||
|
||||
Important examples include amoxicillin and amoxicillin/clavulanic acid, and trimethoprim and trimethoprim/sulfamethoxazole. Needless to say, for these rules to work, both drugs must be available in the data set.
|
||||
|
||||
Since these rules are not officially approved by EUCAST, they are not applied at default. To use these rules, include \code{"other"} to the \code{rules} argument, or use \code{eucast_rules(..., rules = "all")}. You can also set the package option \code{\link[=AMR-options]{AMR_interpretive_rules}}, i.e. run \code{options(AMR_interpretive_rules = "all")}.
|
||||
Since these rules are not officially approved by EUCAST, they are not applied at default. To use these rules, include \code{"other"} to the \code{rules} argument, or use \code{interpretive_rules(..., rules = "all")}. You can also set the package option \code{\link[=AMR-options]{AMR_interpretive_rules}}, i.e. run \code{options(AMR_interpretive_rules = "all")}.
|
||||
}
|
||||
}
|
||||
\section{Download Our Reference Data}{
|
||||
|
||||
@@ -39,9 +39,9 @@ a \link{data.frame}
|
||||
Join the data set \link{microorganisms} easily to an existing data set or to a \link{character} vector.
|
||||
}
|
||||
\details{
|
||||
\strong{Note:} As opposed to the \code{join()} functions of \code{dplyr}, \link{character} vectors are supported and at default existing columns will get a suffix \code{"2"} and the newly joined columns will not get a suffix.
|
||||
**Note:** As opposed to the `join()` functions of `dplyr`, [character] vectors are supported and at default existing columns will get a suffix `"2"` and the newly joined columns will not get a suffix.
|
||||
|
||||
If the \code{dplyr} package is installed, their join functions will be used. Otherwise, the much slower \code{\link[=merge]{merge()}} and \code{\link[=interaction]{interaction()}} functions from base \R will be used.
|
||||
If the `dplyr` package is installed, their join functions will be used. Otherwise, the much slower [merge()] and [interaction()] functions from base \R will be used.
|
||||
}
|
||||
\examples{
|
||||
left_join_microorganisms(as.mo("K. pneumoniae"))
|
||||
|
||||
22
man/mdro.Rd
22
man/mdro.Rd
@@ -67,18 +67,16 @@ eucast_exceptional_phenotypes(x = NULL, only_sir_columns = any(is.sir(x)),
|
||||
\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{
|
||||
\itemize{
|
||||
\item If \code{verbose} is set to \code{TRUE}:\cr
|
||||
A \link{data.frame} containing columns \code{row_number}, \code{microorganism}, \code{MDRO}, \code{reason}, \code{all_nonsusceptible_columns}, \code{guideline}
|
||||
\item CMI 2012 paper - function \code{\link[=mdr_cmi2012]{mdr_cmi2012()}} or \code{\link[=mdro]{mdro()}}:\cr
|
||||
Ordered \link{factor} with levels \code{Negative} < \code{Multi-drug-resistant (MDR)} < \verb{Extensively drug-resistant (XDR)} < \code{Pandrug-resistant (PDR)}
|
||||
\item TB guideline - function \code{\link[=mdr_tb]{mdr_tb()}} or \code{\link[=mdro]{mdro(..., guideline = "TB")}}:\cr
|
||||
Ordered \link{factor} with levels \code{Negative} < \code{Mono-resistant} < \code{Poly-resistant} < \code{Multi-drug-resistant} < \verb{Extensively drug-resistant}
|
||||
\item German guideline - function \code{\link[=mrgn]{mrgn()}} or \code{\link[=mdro]{mdro(..., guideline = "MRGN")}}:\cr
|
||||
Ordered \link{factor} with levels \code{Negative} < \verb{3MRGN} < \verb{4MRGN}
|
||||
\item Everything else, except for custom guidelines:\cr
|
||||
Ordered \link{factor} with levels \code{Negative} < \verb{Positive, unconfirmed} < \code{Positive}. The value \code{"Positive, unconfirmed"} means that, according to the guideline, it is not entirely sure if the isolate is multi-drug resistant and this should be confirmed with additional (e.g. genotypic) tests
|
||||
}
|
||||
- If `verbose` is set to `TRUE`:\cr
|
||||
A [data.frame] containing columns `row_number`, `microorganism`, `MDRO`, `reason`, `all_nonsusceptible_columns`, `guideline`
|
||||
- CMI 2012 paper - function [mdr_cmi2012()] or [mdro()]:\cr
|
||||
Ordered [factor] with levels `Negative` < `Multi-drug-resistant (MDR)` < `Extensively drug-resistant (XDR)` < `Pandrug-resistant (PDR)`
|
||||
- TB guideline - function [mdr_tb()] or [`mdro(..., guideline = "TB")`][mdro()]:\cr
|
||||
Ordered [factor] with levels `Negative` < `Mono-resistant` < `Poly-resistant` < `Multi-drug-resistant` < `Extensively drug-resistant`
|
||||
- German guideline - function [mrgn()] or [`mdro(..., guideline = "MRGN")`][mdro()]:\cr
|
||||
Ordered [factor] with levels `Negative` < `3MRGN` < `4MRGN`
|
||||
- Everything else, except for custom guidelines:\cr
|
||||
Ordered [factor] with levels `Negative` < `Positive, unconfirmed` < `Positive`. The value `"Positive, unconfirmed"` means that, according to the guideline, it is not entirely sure if the isolate is multi-drug resistant and this should be confirmed with additional (e.g. genotypic) tests
|
||||
}
|
||||
\description{
|
||||
Determine which isolates are multidrug-resistant organisms (MDRO) according to international, national, or custom guidelines.
|
||||
|
||||
@@ -168,48 +168,44 @@ The default is \code{FALSE}, which will return a note if outdated taxonomic name
|
||||
\item{property}{One of the column names of the \link{microorganisms} data set: \code{"mo"}, \code{"fullname"}, \code{"status"}, \code{"kingdom"}, \code{"phylum"}, \code{"class"}, \code{"order"}, \code{"family"}, \code{"genus"}, \code{"species"}, \code{"subspecies"}, \code{"rank"}, \code{"ref"}, \code{"oxygen_tolerance"}, \code{"source"}, \code{"lpsn"}, \code{"lpsn_parent"}, \code{"lpsn_renamed_to"}, \code{"mycobank"}, \code{"mycobank_parent"}, \code{"mycobank_renamed_to"}, \code{"gbif"}, \code{"gbif_parent"}, \code{"gbif_renamed_to"}, \code{"prevalence"}, or \code{"snomed"}, or must be \code{"shortname"}.}
|
||||
}
|
||||
\value{
|
||||
\itemize{
|
||||
\item An \link{integer} in case of \code{\link[=mo_year]{mo_year()}}
|
||||
\item An \link[=factor]{ordered factor} in case of \code{\link[=mo_pathogenicity]{mo_pathogenicity()}}
|
||||
\item A \link{list} in case of \code{\link[=mo_taxonomy]{mo_taxonomy()}}, \code{\link[=mo_synonyms]{mo_synonyms()}}, \code{\link[=mo_snomed]{mo_snomed()}}, and \code{\link[=mo_info]{mo_info()}}
|
||||
\item A \link{logical} in case of \code{\link[=mo_is_anaerobic]{mo_is_anaerobic()}}, \code{\link[=mo_is_gram_negative]{mo_is_gram_negative()}}, \code{\link[=mo_is_gram_positive]{mo_is_gram_positive()}}, \code{\link[=mo_is_intrinsic_resistant]{mo_is_intrinsic_resistant()}}, and \code{\link[=mo_is_yeast]{mo_is_yeast()}}
|
||||
\item A named \link{character} in case of \code{\link[=mo_synonyms]{mo_synonyms()}} and \code{\link[=mo_url]{mo_url()}}
|
||||
\item A \link{character} in all other cases
|
||||
}
|
||||
- An [integer] in case of [mo_year()]
|
||||
- An [ordered factor][factor] in case of [mo_pathogenicity()]
|
||||
- A [list] in case of [mo_taxonomy()], [mo_synonyms()], [mo_snomed()], and [mo_info()]
|
||||
- A [logical] in case of [mo_is_anaerobic()], [mo_is_gram_negative()], [mo_is_gram_positive()], [mo_is_intrinsic_resistant()], and [mo_is_yeast()]
|
||||
- A named [character] in case of [mo_synonyms()] and [mo_url()]
|
||||
- A [character] in all other cases
|
||||
}
|
||||
\description{
|
||||
Use these functions to return a specific property of a microorganism based on the latest accepted taxonomy. All input values will be evaluated internally with \code{\link[=as.mo]{as.mo()}}, which makes it possible to use microbial abbreviations, codes and names as input. See \emph{Examples}.
|
||||
}
|
||||
\details{
|
||||
All functions will, at default, \strong{not} keep old taxonomic properties, as synonyms are automatically replaced with the current taxonomy. Take for example \emph{Enterobacter aerogenes}, which was initially named in 1960 but renamed to \emph{Klebsiella aerogenes} in 2017:
|
||||
\itemize{
|
||||
\item \code{mo_genus("Enterobacter aerogenes")} will return \code{"Klebsiella"} (with a note about the renaming)
|
||||
\item \code{mo_genus("Enterobacter aerogenes", keep_synonyms = TRUE)} will return \code{"Enterobacter"} (with a once-per-session warning that the name is outdated)
|
||||
\item \code{mo_ref("Enterobacter aerogenes")} will return \code{"Tindall et al., 2017"} (with a note about the renaming)
|
||||
\item \code{mo_ref("Enterobacter aerogenes", keep_synonyms = TRUE)} will return \code{"Hormaeche et al., 1960"} (with a once-per-session warning that the name is outdated)
|
||||
}
|
||||
All functions will, at default, **not** keep old taxonomic properties, as synonyms are automatically replaced with the current taxonomy. Take for example *Enterobacter aerogenes*, which was initially named in 1960 but renamed to *Klebsiella aerogenes* in 2017:
|
||||
- `mo_genus("Enterobacter aerogenes")` will return `"Klebsiella"` (with a note about the renaming)
|
||||
- `mo_genus("Enterobacter aerogenes", keep_synonyms = TRUE)` will return `"Enterobacter"` (with a once-per-session warning that the name is outdated)
|
||||
- `mo_ref("Enterobacter aerogenes")` will return `"Tindall et al., 2017"` (with a note about the renaming)
|
||||
- `mo_ref("Enterobacter aerogenes", keep_synonyms = TRUE)` will return `"Hormaeche et al., 1960"` (with a once-per-session warning that the name is outdated)
|
||||
|
||||
The short name (\code{\link[=mo_shortname]{mo_shortname()}}) returns the first character of the genus and the full species, such as \code{"E. coli"}, for species and subspecies. Exceptions are abbreviations of staphylococci (such as \emph{"CoNS"}, Coagulase-Negative Staphylococci) and beta-haemolytic streptococci (such as \emph{"GBS"}, Group B Streptococci). Please bear in mind that e.g. \emph{E. coli} could mean \emph{Escherichia coli} (kingdom of Bacteria) as well as \emph{Entamoeba coli} (kingdom of Protozoa). Returning to the full name will be done using \code{\link[=as.mo]{as.mo()}} internally, giving priority to bacteria and human pathogens, i.e. \code{"E. coli"} will be considered \emph{Escherichia coli}. As a result, \code{mo_fullname(mo_shortname("Entamoeba coli"))} returns \code{"Escherichia coli"}.
|
||||
The short name ([mo_shortname()]) returns the first character of the genus and the full species, such as `"E. coli"`, for species and subspecies. Exceptions are abbreviations of staphylococci (such as *"CoNS"*, Coagulase-Negative Staphylococci) and beta-haemolytic streptococci (such as *"GBS"*, Group B Streptococci). Please bear in mind that e.g. *E. coli* could mean *Escherichia coli* (kingdom of Bacteria) as well as *Entamoeba coli* (kingdom of Protozoa). Returning to the full name will be done using [as.mo()] internally, giving priority to bacteria and human pathogens, i.e. `"E. coli"` will be considered *Escherichia coli*. As a result, `mo_fullname(mo_shortname("Entamoeba coli"))` returns `"Escherichia coli"`.
|
||||
|
||||
Since the top-level of the taxonomy is sometimes referred to as 'kingdom' and sometimes as 'domain', the functions \code{\link[=mo_kingdom]{mo_kingdom()}} and \code{\link[=mo_domain]{mo_domain()}} return the exact same results.
|
||||
Since the top-level of the taxonomy is sometimes referred to as 'kingdom' and sometimes as 'domain', the functions [mo_kingdom()] and [mo_domain()] return the exact same results.
|
||||
|
||||
Determination of human pathogenicity (\code{\link[=mo_pathogenicity]{mo_pathogenicity()}}) is strongly based on Bartlett \emph{et al.} (2022, \doi{10.1099/mic.0.001269}). This function returns a \link{factor} with the levels \emph{Pathogenic}, \emph{Potentially pathogenic}, \emph{Non-pathogenic}, and \emph{Unknown}.
|
||||
Determination of human pathogenicity ([mo_pathogenicity()]) is strongly based on Bartlett *et al.* (2022, \doi{10.1099/mic.0.001269}). This function returns a [factor] with the levels *Pathogenic*, *Potentially pathogenic*, *Non-pathogenic*, and *Unknown*.
|
||||
|
||||
Determination of the Gram stain (\code{\link[=mo_gramstain]{mo_gramstain()}}) will be based on the taxonomic kingdom and phylum. Originally, Cavalier-Smith defined the so-called subkingdoms Negibacteria and Posibacteria (2002, \href{https://pubmed.ncbi.nlm.nih.gov/11837318/}{PMID 11837318}), and only considered these phyla as Posibacteria: Actinobacteria, Chloroflexi, Firmicutes, and Tenericutes. These phyla were later renamed to Actinomycetota, Chloroflexota, Bacillota, and Mycoplasmatota (2021, \href{https://pubmed.ncbi.nlm.nih.gov/34694987/}{PMID 34694987}). Bacteria in these phyla are considered Gram-positive in this \code{AMR} package, except for members of the class Negativicutes (within phylum Bacillota) which are Gram-negative. All other bacteria are considered Gram-negative. Species outside the kingdom of Bacteria will return a value \code{NA}. Functions \code{\link[=mo_is_gram_negative]{mo_is_gram_negative()}} and \code{\link[=mo_is_gram_positive]{mo_is_gram_positive()}} always return \code{TRUE} or \code{FALSE} (or \code{NA} when the input is \code{NA} or the MO code is \code{UNKNOWN}), thus always return \code{FALSE} for species outside the taxonomic kingdom of Bacteria.
|
||||
Determination of the Gram stain ([mo_gramstain()]) will be based on the taxonomic kingdom and phylum. Originally, Cavalier-Smith defined the so-called subkingdoms Negibacteria and Posibacteria (2002, [PMID 11837318](https://pubmed.ncbi.nlm.nih.gov/11837318/)), and only considered these phyla as Posibacteria: Actinobacteria, Chloroflexi, Firmicutes, and Tenericutes. These phyla were later renamed to Actinomycetota, Chloroflexota, Bacillota, and Mycoplasmatota (2021, [PMID 34694987](https://pubmed.ncbi.nlm.nih.gov/34694987/)). Bacteria in these phyla are considered Gram-positive in this `AMR` package, except for members of the class Negativicutes (within phylum Bacillota) which are Gram-negative. All other bacteria are considered Gram-negative. Species outside the kingdom of Bacteria will return a value `NA`. Functions [mo_is_gram_negative()] and [mo_is_gram_positive()] always return `TRUE` or `FALSE` (or `NA` when the input is `NA` or the MO code is `UNKNOWN`), thus always return `FALSE` for species outside the taxonomic kingdom of Bacteria.
|
||||
|
||||
Determination of yeasts (\code{\link[=mo_is_yeast]{mo_is_yeast()}}) will be based on the taxonomic kingdom and class. \emph{Budding yeasts} are yeasts that reproduce asexually through a process called budding, where a new cell develops from a small protrusion on the parent cell. Taxonomically, these are members of the phylum Ascomycota, class Saccharomycetes (also called Hemiascomycetes) or Pichiomycetes. \emph{True yeasts} quite specifically refers to yeasts in the underlying order Saccharomycetales (such as \emph{Saccharomyces cerevisiae}). Thus, for all microorganisms that are member of the taxonomic class Saccharomycetes or Pichiomycetes, the function will return \code{TRUE}. It returns \code{FALSE} otherwise (or \code{NA} when the input is \code{NA} or the MO code is \code{UNKNOWN}).
|
||||
Determination of yeasts ([mo_is_yeast()]) will be based on the taxonomic kingdom and class. *Budding yeasts* are yeasts that reproduce asexually through a process called budding, where a new cell develops from a small protrusion on the parent cell. Taxonomically, these are members of the phylum Ascomycota, class Saccharomycetes (also called Hemiascomycetes) or Pichiomycetes. *True yeasts* quite specifically refers to yeasts in the underlying order Saccharomycetales (such as *Saccharomyces cerevisiae*). Thus, for all microorganisms that are member of the taxonomic class Saccharomycetes or Pichiomycetes, the function will return `TRUE`. It returns `FALSE` otherwise (or `NA` when the input is `NA` or the MO code is `UNKNOWN`).
|
||||
|
||||
Determination of intrinsic resistance (\code{\link[=mo_is_intrinsic_resistant]{mo_is_intrinsic_resistant()}}) will be based on the \link{intrinsic_resistant} data set, which is based on \href{https://www.eucast.org/bacteria/important-additional-information/expert-rules/}{'EUCAST Expected Resistant Phenotypes' v1.2} (2023). The \code{\link[=mo_is_intrinsic_resistant]{mo_is_intrinsic_resistant()}} function can be vectorised over both argument \code{x} (input for microorganisms) and \code{ab} (input for antimicrobials).
|
||||
Determination of intrinsic resistance ([mo_is_intrinsic_resistant()]) will be based on the [intrinsic_resistant] data set, which is based on `r format_eucast_version_nr(names(EUCAST_VERSION_EXPECTED_PHENOTYPES[1]))`. The [mo_is_intrinsic_resistant()] function can be vectorised over both argument `x` (input for microorganisms) and `ab` (input for antimicrobials).
|
||||
|
||||
Determination of bacterial oxygen tolerance (\code{\link[=mo_oxygen_tolerance]{mo_oxygen_tolerance()}}) will be based on BacDive, see \emph{Source}. The function \code{\link[=mo_is_anaerobic]{mo_is_anaerobic()}} only returns \code{TRUE} if the oxygen tolerance is \code{"anaerobe"}, indicting an obligate anaerobic species or genus. It always returns \code{FALSE} for species outside the taxonomic kingdom of Bacteria.
|
||||
Determination of bacterial oxygen tolerance ([mo_oxygen_tolerance()]) will be based on BacDive, see *Source*. The function [mo_is_anaerobic()] only returns `TRUE` if the oxygen tolerance is `"anaerobe"`, indicting an obligate anaerobic species or genus. It always returns `FALSE` for species outside the taxonomic kingdom of Bacteria.
|
||||
|
||||
The function \code{\link[=mo_url]{mo_url()}} will return the direct URL to the online database entry, which also shows the scientific reference of the concerned species. \href{https://www.mycobank.org}{This MycoBank URL} will be used for fungi wherever available , \href{https://www.mycobank.org}{this LPSN URL} for bacteria wherever available, and \href{https://www.gbif.org}{this GBIF link} otherwise.
|
||||
The function [mo_url()] will return the direct URL to the online database entry, which also shows the scientific reference of the concerned species. [This MycoBank URL](`r TAXONOMY_VERSION$MycoBank$url`) will be used for fungi wherever available , [this LPSN URL](`r TAXONOMY_VERSION$MycoBank$url`) for bacteria wherever available, and [this GBIF link](`r TAXONOMY_VERSION$GBIF$url`) otherwise.
|
||||
|
||||
SNOMED codes (\code{\link[=mo_snomed]{mo_snomed()}}) was last updated on July 16th, 2024. See \emph{Source} and the \link{microorganisms} data set for more info.
|
||||
SNOMED codes ([mo_snomed()]) was last updated on `r documentation_date(TAXONOMY_VERSION$SNOMED$accessed_date)`. See *Source* and the [microorganisms] data set for more info.
|
||||
|
||||
Old taxonomic names (so-called 'synonyms') can be retrieved with \code{\link[=mo_synonyms]{mo_synonyms()}} (which will have the scientific reference as \link[base:names]{name}), the current taxonomic name can be retrieved with \code{\link[=mo_current]{mo_current()}}. Both functions return full names.
|
||||
Old taxonomic names (so-called 'synonyms') can be retrieved with [mo_synonyms()] (which will have the scientific reference as [name][base::names()]), the current taxonomic name can be retrieved with [mo_current()]. Both functions return full names.
|
||||
|
||||
All output \link[=translate]{will be translated} where possible.
|
||||
All output [will be translated][translate] where possible.
|
||||
}
|
||||
\section{Matching Score for Microorganisms}{
|
||||
|
||||
|
||||
@@ -30,6 +30,15 @@
|
||||
test_that("test-_deprecated.R", {
|
||||
skip_on_cran()
|
||||
|
||||
expect_warning(example_isolates[, ab_class("mycobact")])
|
||||
expect_warning(example_isolates[, ab_selector(name %like% "trim")])
|
||||
if (getRversion() > "4.0.0") {
|
||||
expect_warning(example_isolates[, ab_class("mycobact")])
|
||||
expect_warning(example_isolates[, ab_selector(name %like% "trim")])
|
||||
|
||||
# deprecated custom_interpretive_rules() still works and emits a warning
|
||||
expect_warning(
|
||||
x_old <- custom_eucast_rules(AMC == "R" ~ aminopenicillins == "R"),
|
||||
regexp = "custom_eucast_rules"
|
||||
)
|
||||
expect_inherits(x_old, "custom_interpretive_rules")
|
||||
}
|
||||
})
|
||||
|
||||
@@ -152,11 +152,14 @@ test_that("test-antibiogram.R", {
|
||||
expect_equal(colnames(wisca_par), colnames(wisca_seq))
|
||||
expect_true(isTRUE(attributes(wisca_par)$wisca))
|
||||
|
||||
# 2. coverage values fall within [0, 100] (basic sanity)
|
||||
# 2. coverage values are non-NA and fall within [0, 1]
|
||||
ln <- attributes(wisca_par)$long_numeric
|
||||
expect_true(all(ln$coverage >= 0 & ln$coverage <= 1, na.rm = TRUE))
|
||||
expect_true(all(ln$lower_ci <= ln$coverage, na.rm = TRUE))
|
||||
expect_true(all(ln$upper_ci >= ln$coverage, na.rm = TRUE))
|
||||
expect_false(anyNA(ln$coverage))
|
||||
expect_false(anyNA(ln$lower_ci))
|
||||
expect_false(anyNA(ln$upper_ci))
|
||||
expect_true(all(ln$coverage >= 0 & ln$coverage <= 1))
|
||||
expect_true(all(ln$lower_ci <= ln$coverage))
|
||||
expect_true(all(ln$upper_ci >= ln$coverage))
|
||||
|
||||
# 3. a second parallel run gives the same column names
|
||||
wisca_par2 <- suppressWarnings(suppressMessages(
|
||||
|
||||
@@ -53,12 +53,12 @@ test_that("test-data.R", {
|
||||
expect_false(anyNA(microorganisms.codes$mo))
|
||||
expect_true(all(dosage$ab %in% AMR::antimicrobials$ab))
|
||||
expect_true(all(dosage$name %in% AMR::antimicrobials$name))
|
||||
eucast_abx <- AMR:::EUCAST_RULES_DF$and_these_antibiotics
|
||||
eucast_abx <- unique(unlist(strsplit(eucast_abx[!is.na(eucast_abx)], ", +")))
|
||||
expect_true(all(eucast_abx %in% AMR::antimicrobials$ab),
|
||||
interpretive_abx <- AMR:::INTERPRETIVE_RULES_DF$and_these_antibiotics
|
||||
interpretive_abx <- unique(unlist(strsplit(interpretive_abx[!is.na(interpretive_abx)], ", +")))
|
||||
expect_true(all(interpretive_abx %in% AMR::antimicrobials$ab),
|
||||
info = paste0(
|
||||
"Missing in `antimicrobials` data set: ",
|
||||
toString(eucast_abx[which(!eucast_abx %in% AMR::antimicrobials$ab)])
|
||||
toString(interpretive_abx[which(!interpretive_abx %in% AMR::antimicrobials$ab)])
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -27,13 +27,14 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
test_that("test-eucast_rules.R", {
|
||||
test_that("test-interpretive_rules.R", {
|
||||
skip_on_cran()
|
||||
|
||||
# thoroughly check input table
|
||||
expect_equal(
|
||||
sort(colnames(AMR:::EUCAST_RULES_DF)),
|
||||
sort(colnames(AMR:::INTERPRETIVE_RULES_DF)),
|
||||
sort(c(
|
||||
"rule.provider",
|
||||
"if_mo_property", "like.is.one_of", "this_value",
|
||||
"and_these_antibiotics", "have_these_values",
|
||||
"then_change_these_antibiotics", "to_value",
|
||||
@@ -42,7 +43,7 @@ test_that("test-eucast_rules.R", {
|
||||
"note"
|
||||
))
|
||||
)
|
||||
MOs_mentioned <- unique(AMR:::EUCAST_RULES_DF$this_value)
|
||||
MOs_mentioned <- unique(AMR:::INTERPRETIVE_RULES_DF$this_value)
|
||||
MOs_mentioned <- sort(trimws(unlist(strsplit(MOs_mentioned[!AMR:::is_valid_regex(MOs_mentioned)], ",", fixed = TRUE))))
|
||||
MOs_test <- suppressWarnings(
|
||||
trimws(paste(
|
||||
@@ -54,19 +55,19 @@ test_that("test-eucast_rules.R", {
|
||||
MOs_test[MOs_test == ""] <- mo_fullname(MOs_mentioned[MOs_test == ""], keep_synonyms = TRUE, language = NULL)
|
||||
expect_equal(MOs_mentioned, MOs_test)
|
||||
|
||||
expect_error(suppressWarnings(eucast_rules(example_isolates, col_mo = "Non-existing")))
|
||||
expect_error(eucast_rules(x = "text"))
|
||||
expect_error(eucast_rules(data.frame(a = "test")))
|
||||
expect_error(eucast_rules(data.frame(mo = "test"), rules = "invalid rules set"))
|
||||
expect_error(suppressWarnings(interpretive_rules(example_isolates, col_mo = "Non-existing")))
|
||||
expect_error(interpretive_rules(x = "text"))
|
||||
expect_error(interpretive_rules(data.frame(a = "test")))
|
||||
expect_error(interpretive_rules(data.frame(mo = "test"), rules = "invalid rules set"))
|
||||
|
||||
# expect_warning(eucast_rules(data.frame(mo = "Escherichia coli", vancomycin = "S", stringsAsFactors = TRUE)))
|
||||
# expect_warning(interpretive_rules(data.frame(mo = "Escherichia coli", vancomycin = "S", stringsAsFactors = TRUE)))
|
||||
|
||||
expect_identical(
|
||||
colnames(example_isolates),
|
||||
colnames(suppressWarnings(eucast_rules(example_isolates, info = FALSE)))
|
||||
colnames(suppressWarnings(interpretive_rules(example_isolates, info = FALSE)))
|
||||
)
|
||||
|
||||
expect_output(suppressMessages(eucast_rules(example_isolates, info = TRUE)))
|
||||
expect_output(suppressMessages(interpretive_rules(example_isolates, info = TRUE)))
|
||||
|
||||
a <- data.frame(
|
||||
mo = c(
|
||||
@@ -86,8 +87,8 @@ test_that("test-eucast_rules.R", {
|
||||
amox = "R", # Amoxicillin
|
||||
stringsAsFactors = FALSE
|
||||
)
|
||||
expect_identical(suppressWarnings(eucast_rules(a, "mo", info = FALSE)), b)
|
||||
expect_output(suppressMessages(suppressWarnings(eucast_rules(a, "mo", info = TRUE))))
|
||||
expect_identical(suppressWarnings(interpretive_rules(a, "mo", info = FALSE)), b)
|
||||
expect_output(suppressMessages(suppressWarnings(interpretive_rules(a, "mo", info = TRUE))))
|
||||
|
||||
a <- data.frame(
|
||||
mo = c(
|
||||
@@ -105,7 +106,7 @@ test_that("test-eucast_rules.R", {
|
||||
COL = "R", # Colistin
|
||||
stringsAsFactors = FALSE
|
||||
)
|
||||
expect_equal(suppressWarnings(eucast_rules(a, "mo", info = FALSE)), b)
|
||||
expect_equal(suppressWarnings(interpretive_rules(a, "mo", info = FALSE)), b)
|
||||
|
||||
# piperacillin must be R in Enterobacteriaceae when tica is R
|
||||
if (AMR:::pkg_is_available("dplyr", min_version = "1.0.0", also_load = TRUE)) {
|
||||
@@ -117,7 +118,7 @@ test_that("test-eucast_rules.R", {
|
||||
TIC = as.sir("R"),
|
||||
PIP = as.sir("S")
|
||||
) %>%
|
||||
eucast_rules(col_mo = "mo", version_expertrules = 3.1, rules = "expert", info = FALSE, overwrite = TRUE) %>%
|
||||
interpretive_rules(col_mo = "mo", version_expertrules = 3.1, rules = "expert", info = FALSE, overwrite = TRUE) %>%
|
||||
pull(PIP) %>%
|
||||
unique() %>%
|
||||
as.character()
|
||||
@@ -127,7 +128,7 @@ test_that("test-eucast_rules.R", {
|
||||
}
|
||||
|
||||
# azithromycin and clarythromycin must be equal to Erythromycin
|
||||
a <- suppressWarnings(as.sir(eucast_rules(
|
||||
a <- suppressWarnings(as.sir(interpretive_rules(
|
||||
data.frame(
|
||||
mo = example_isolates$mo,
|
||||
ERY = example_isolates$ERY,
|
||||
@@ -149,7 +150,7 @@ test_that("test-eucast_rules.R", {
|
||||
# amox is inferred by benzylpenicillin in Kingella kingae
|
||||
expect_equal(
|
||||
suppressWarnings(
|
||||
as.list(eucast_rules(
|
||||
as.list(interpretive_rules(
|
||||
data.frame(
|
||||
mo = as.mo("Kingella kingae"),
|
||||
PEN = "S",
|
||||
@@ -164,16 +165,16 @@ test_that("test-eucast_rules.R", {
|
||||
|
||||
# also test norf
|
||||
if (AMR:::pkg_is_available("dplyr", min_version = "1.0.0", also_load = TRUE)) {
|
||||
expect_output(suppressWarnings(eucast_rules(example_isolates %>% mutate(NOR = "S", NAL = "S"), info = TRUE)))
|
||||
expect_output(suppressWarnings(interpretive_rules(example_isolates %>% mutate(NOR = "S", NAL = "S"), info = TRUE)))
|
||||
}
|
||||
|
||||
# check verbose output
|
||||
expect_output(suppressWarnings(eucast_rules(example_isolates, verbose = TRUE, rules = "all", info = TRUE)))
|
||||
expect_output(suppressWarnings(interpretive_rules(example_isolates, verbose = TRUE, rules = "all", info = TRUE)))
|
||||
|
||||
# AmpC de-repressed cephalo mutants
|
||||
|
||||
expect_identical(
|
||||
eucast_rules(
|
||||
interpretive_rules(
|
||||
data.frame(
|
||||
mo = c("Escherichia coli", "Enterobacter cloacae"),
|
||||
cefotax = as.sir(c("S", "S"))
|
||||
@@ -187,7 +188,7 @@ test_that("test-eucast_rules.R", {
|
||||
)
|
||||
|
||||
expect_identical(
|
||||
eucast_rules(
|
||||
interpretive_rules(
|
||||
data.frame(
|
||||
mo = c("Escherichia coli", "Enterobacter cloacae"),
|
||||
cefotax = as.sir(c("S", "S"))
|
||||
@@ -201,7 +202,7 @@ test_that("test-eucast_rules.R", {
|
||||
)
|
||||
|
||||
expect_identical(
|
||||
eucast_rules(
|
||||
interpretive_rules(
|
||||
data.frame(
|
||||
mo = c("Escherichia coli", "Enterobacter cloacae"),
|
||||
cefotax = as.sir(c("S", "S"))
|
||||
@@ -219,7 +220,7 @@ test_that("test-eucast_rules.R", {
|
||||
expect_inherits(eucast_dosage(c("tobra", "genta", "cipro")), "data.frame")
|
||||
|
||||
|
||||
x <- custom_eucast_rules(
|
||||
x <- custom_interpretive_rules(
|
||||
AMC == "R" & genus == "Klebsiella" ~ aminopenicillins == "R",
|
||||
AMC == "I" & genus == "Klebsiella" ~ aminopenicillins == "I",
|
||||
AMX == "S" ~ AMC == "S"
|
||||
@@ -230,7 +231,7 @@ test_that("test-eucast_rules.R", {
|
||||
|
||||
# this custom rules makes 8 changes
|
||||
expect_equal(
|
||||
nrow(eucast_rules(example_isolates,
|
||||
nrow(interpretive_rules(example_isolates,
|
||||
rules = "custom",
|
||||
custom_rules = x,
|
||||
info = FALSE,
|
||||
@@ -240,4 +241,10 @@ test_that("test-eucast_rules.R", {
|
||||
8,
|
||||
tolerance = 0.5
|
||||
)
|
||||
|
||||
# clsi_rules() no longer errors (returns data unchanged until CLSI rows are added)
|
||||
expect_identical(
|
||||
suppressWarnings(clsi_rules(example_isolates, info = FALSE)),
|
||||
example_isolates
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user