mirror of
https://github.com/msberends/AMR.git
synced 2025-07-09 02:03:04 +02:00
(v1.4.0.9032) auto-data guessing for functions
This commit is contained in:
@ -251,7 +251,7 @@ word_wrap <- function(...,
|
||||
msg <- gsub("\n", "*|*", msg, fixed = TRUE)
|
||||
|
||||
if (isTRUE(as_note)) {
|
||||
msg <- paste0("NOTE: ", gsub("note:? ?", "", msg, ignore.case = TRUE))
|
||||
msg <- paste0("NOTE: ", gsub("^note:? ?", "", msg, ignore.case = TRUE))
|
||||
}
|
||||
|
||||
# we need to correct for already applied style, that adds text like "\033[31m\"
|
||||
@ -510,6 +510,21 @@ meet_criteria <- function(object,
|
||||
return(invisible())
|
||||
}
|
||||
|
||||
get_current_data <- function(arg_name, call) {
|
||||
# this mimics dplyr::cur_data_all for users that use our content-aware functions in dplyr verbs
|
||||
cur_data_all_dplyr <- import_fn("cur_data_all", "dplyr", error_on_fail = FALSE)
|
||||
if (is.null(cur_data_all_dplyr)) {
|
||||
# dplyr not installed
|
||||
stop_("argument `", arg_name, "` is missing, with no default", call = call)
|
||||
}
|
||||
tryCatch(cur_data_all_dplyr(),
|
||||
# dplyr installed, but not used inside dplyr verb
|
||||
error = function(e) stop_("argument `", arg_name, "` is missing with no default ",
|
||||
"or function not used inside a valid dplyr verb",
|
||||
# tryCatch adds 4 system calls, subtract them
|
||||
call = call - 4))
|
||||
}
|
||||
|
||||
has_colour <- function() {
|
||||
# this is a base R version of crayon::has_color
|
||||
enabled <- getOption("crayon.enabled")
|
||||
@ -567,7 +582,7 @@ has_colour <- function() {
|
||||
perl = TRUE)
|
||||
}
|
||||
|
||||
# the crayon colours
|
||||
# set colours if console has_colour()
|
||||
try_colour <- function(..., before, after, collapse = " ") {
|
||||
txt <- paste0(unlist(list(...)), collapse = collapse)
|
||||
if (isTRUE(has_colour())) {
|
||||
@ -611,7 +626,7 @@ font_grey <- function(..., collapse = " ") {
|
||||
try_colour(..., before = "\033[38;5;249m", after = "\033[39m", collapse = collapse)
|
||||
}
|
||||
font_grey_bg <- function(..., collapse = " ") {
|
||||
try_colour(..., before = "\033[48;5;253m", after = "\033[49m", collapse = collapse)
|
||||
try_colour(..., before = "\033[48;5;255m", after = "\033[49m", collapse = collapse)
|
||||
}
|
||||
font_green_bg <- function(..., collapse = " ") {
|
||||
try_colour(..., before = "\033[42m", after = "\033[49m", collapse = collapse)
|
||||
@ -659,10 +674,12 @@ progress_ticker <- function(n = 1, n_min = 0, ...) {
|
||||
}
|
||||
|
||||
set_clean_class <- function(x, new_class) {
|
||||
# return the object with only the new class and no additional attributes where possible
|
||||
if (is.null(x)) {
|
||||
x <- NA_character_
|
||||
}
|
||||
if (is.factor(x)) {
|
||||
# keep only levels and remove all other attributes
|
||||
lvls <- levels(x)
|
||||
attributes(x) <- NULL
|
||||
levels(x) <- lvls
|
||||
|
@ -179,10 +179,11 @@ ab_selector <- function(ab_class, function_name) {
|
||||
message_("No antimicrobial agents of class ", ab_group, " found", examples, ".")
|
||||
} else {
|
||||
message_("Selecting ", ab_group, ": ",
|
||||
paste(paste0("`", font_bold(agents, collapse = NULL),
|
||||
"` (", ab_name(names(agents), tolower = TRUE, language = NULL), ")"),
|
||||
paste(paste0("'", font_bold(agents, collapse = NULL),
|
||||
"' (", ab_name(names(agents), tolower = TRUE, language = NULL), ")"),
|
||||
collapse = ", "),
|
||||
as_note = FALSE)
|
||||
as_note = FALSE,
|
||||
extra_indent = nchar(paste0("Selecting ", ab_group, ": ")))
|
||||
}
|
||||
unname(agents)
|
||||
}
|
||||
|
@ -620,8 +620,8 @@ eucast_rules <- function(x,
|
||||
if (any(c("all", "other") %in% rules)) {
|
||||
if (info == TRUE) {
|
||||
cat(font_bold(paste0("\nRules by this AMR package (",
|
||||
font_red(paste0("v", utils::packageVersion("AMR"), ", ",
|
||||
format(utils::packageDate("AMR"), "%Y"))), "), see ?eucast_rules\n")))
|
||||
font_red(paste0("v", utils::packageDescription("AMR")$Version, ", ",
|
||||
format(utils::packageDescription("AMR")$Date, "%Y"))), "), see ?eucast_rules\n")))
|
||||
}
|
||||
|
||||
ab_enzyme <- subset(antibiotics, name %like% "/")[, c("ab", "name")]
|
||||
@ -639,7 +639,7 @@ eucast_rules <- function(x,
|
||||
run_changes <- edit_rsi(x = x,
|
||||
col_mo = col_mo,
|
||||
to = "R",
|
||||
rule = c(rule_current, "Other rules", "", paste0("Non-EUCAST: AMR package v", utils::packageVersion("AMR"))),
|
||||
rule = c(rule_current, "Other rules", "", paste0("Non-EUCAST: AMR package v", utils::packageDescription("AMR")$Version)),
|
||||
rows = which(as.rsi_no_warning(x[, cols_ab[ab_enzyme[i, ]$ab]]) == "R"),
|
||||
cols = cols_ab[ab_enzyme[i, ]$base_ab],
|
||||
last_verbose_info = verbose_info,
|
||||
@ -669,7 +669,7 @@ eucast_rules <- function(x,
|
||||
run_changes <- edit_rsi(x = x,
|
||||
col_mo = col_mo,
|
||||
to = "S",
|
||||
rule = c(rule_current, "Other rules", "", paste0("Non-EUCAST: AMR package v", utils::packageVersion("AMR"))),
|
||||
rule = c(rule_current, "Other rules", "", paste0("Non-EUCAST: AMR package v", utils::packageDescription("AMR")$Version)),
|
||||
rows = which(as.rsi_no_warning(x[, cols_ab[ab_enzyme[i, ]$base_ab]]) == "S"),
|
||||
cols = cols_ab[ab_enzyme[i, ]$ab],
|
||||
last_verbose_info = verbose_info,
|
||||
|
@ -27,7 +27,7 @@
|
||||
#'
|
||||
#' Determine first (weighted) isolates of all microorganisms of every patient per episode and (if needed) per specimen type. To determine patient episodes not necessarily based on microorganisms, use [is_new_episode()] that also supports grouping with the `dplyr` package.
|
||||
#' @inheritSection lifecycle Stable lifecycle
|
||||
#' @param x a [data.frame] containing isolates.
|
||||
#' @param x a [data.frame] containing isolates. Can be omitted when used inside `dplyr` verbs, such as `filter()`, `mutate()` and `summarise()`.
|
||||
#' @param col_date column name of the result date (or date that is was received on the lab), defaults to the first column with a date class
|
||||
#' @param col_patient_id column name of the unique IDs of the patients, defaults to the first column that starts with 'patient' or 'patid' (case insensitive)
|
||||
#' @param col_mo column name of the IDs of the microorganisms (see [as.mo()]), defaults to the first column of class [`mo`]. Values will be coerced using [as.mo()].
|
||||
@ -45,7 +45,10 @@
|
||||
#' @param info print progress
|
||||
#' @param include_unknown logical to determine whether 'unknown' microorganisms should be included too, i.e. microbial code `"UNKNOWN"`, which defaults to `FALSE`. For WHONET users, this means that all records with organism code `"con"` (*contamination*) will be excluded at default. Isolates with a microbial ID of `NA` will always be excluded as first isolate.
|
||||
#' @param ... parameters passed on to [first_isolate()] when using [filter_first_isolate()], or parameters passed on to [key_antibiotics()] when using [filter_first_weighted_isolate()]
|
||||
#' @details The [first_isolate()] function is a wrapper around the [is_new_episode()] function, but more efficient for data sets containing microorganism codes or names.
|
||||
#' @details
|
||||
#' These functions are context-aware when used inside `dplyr` verbs, such as `filter()`, `mutate()` and `summarise()`. This means that then the `x` parameter can be omitted, please see *Examples*.
|
||||
#'
|
||||
#' The [first_isolate()] function is a wrapper around the [is_new_episode()] function, but more efficient for data sets containing microorganism codes or names.
|
||||
#'
|
||||
#' All isolates with a microbial ID of `NA` will be excluded as first isolate.
|
||||
#'
|
||||
@ -61,7 +64,7 @@
|
||||
#' ```
|
||||
#' x[first_isolate(x, ...), ]
|
||||
#'
|
||||
#' x %>% filter(first_isolate(x, ...))
|
||||
#' x %>% filter(first_isolate(...))
|
||||
#' ```
|
||||
#'
|
||||
#' The function [filter_first_weighted_isolate()] is essentially equal to:
|
||||
@ -109,6 +112,8 @@
|
||||
#'
|
||||
#' # short-hand versions:
|
||||
#' example_isolates %>%
|
||||
#' filter(first_isolate())
|
||||
#' example_isolates %>%
|
||||
#' filter_first_isolate()
|
||||
#'
|
||||
#' example_isolates %>%
|
||||
@ -150,6 +155,9 @@ first_isolate <- function(x,
|
||||
info = interactive(),
|
||||
include_unknown = FALSE,
|
||||
...) {
|
||||
if (missing(x)) {
|
||||
x <- get_current_data(arg_name = "x", call = -2)
|
||||
}
|
||||
meet_criteria(x, allow_class = "data.frame") # also checks dimensions to be >0
|
||||
meet_criteria(col_date, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
|
||||
meet_criteria(col_patient_id, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
|
||||
@ -425,7 +433,7 @@ first_isolate <- function(x,
|
||||
message_(ifelse(include_unknown == TRUE, "Included ", "Excluded "),
|
||||
format(sum(x$newvar_mo == "UNKNOWN", na.rm = TRUE),
|
||||
decimal.mark = decimal.mark, big.mark = big.mark),
|
||||
" isolates with a microbial ID 'UNKNOWN' (column `", font_bold(col_mo), "`)")
|
||||
" isolates with a microbial ID 'UNKNOWN' (column '", font_bold(col_mo), "')")
|
||||
}
|
||||
x[which(x$newvar_mo == "UNKNOWN"), "newvar_first_isolate"] <- include_unknown
|
||||
|
||||
@ -433,7 +441,7 @@ first_isolate <- function(x,
|
||||
if (any(is.na(x$newvar_mo)) & info == TRUE) {
|
||||
message_("Excluded ", format(sum(is.na(x$newvar_mo), na.rm = TRUE),
|
||||
decimal.mark = decimal.mark, big.mark = big.mark),
|
||||
" isolates with a microbial ID 'NA' (column `", font_bold(col_mo), "`)")
|
||||
" isolates with a microbial ID 'NA' (column '", font_bold(col_mo), "')")
|
||||
}
|
||||
x[which(is.na(x$newvar_mo)), "newvar_first_isolate"] <- FALSE
|
||||
|
||||
|
@ -23,7 +23,8 @@
|
||||
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
|
||||
# ==================================================================== #
|
||||
|
||||
globalVariables(c(".rowid",
|
||||
globalVariables(c("...length", # for pm_group_split() on R 3.3
|
||||
".rowid",
|
||||
"ab",
|
||||
"ab_txt",
|
||||
"angle",
|
||||
|
@ -43,7 +43,7 @@
|
||||
#'
|
||||
#' is_new_episode(example_isolates$date)
|
||||
#' is_new_episode(example_isolates$date, episode_days = 60)
|
||||
#'
|
||||
#' #' \donttest{
|
||||
#' if (require("dplyr")) {
|
||||
#' # is_new_episode() can also be used in dplyr verbs to determine patient
|
||||
#' # episodes based on any (combination of) grouping variables:
|
||||
@ -79,6 +79,7 @@
|
||||
#' group_by(patient_id, mo, hospital_id, ward_icu) %>%
|
||||
#' mutate(flag_episode = is_new_episode(date))
|
||||
#' }
|
||||
#' }
|
||||
is_new_episode <- function(x, episode_days = 365, ...) {
|
||||
meet_criteria(x, allow_class = c("Date", "POSIXt"))
|
||||
meet_criteria(episode_days, allow_class = c("numeric", "double", "integer"), has_length = 1)
|
||||
|
@ -25,9 +25,9 @@
|
||||
|
||||
#' Key antibiotics for first *weighted* isolates
|
||||
#'
|
||||
#' These function can be used to determine first isolates (see [first_isolate()]). Using key antibiotics to determine first isolates is more reliable than without key antibiotics. These selected isolates will then be called first *weighted* isolates.
|
||||
#' These function can be used to determine first isolates (see [first_isolate()]). Using key antibiotics to determine first isolates is more reliable than without key antibiotics. These selected isolates can then be called first *weighted* isolates.
|
||||
#' @inheritSection lifecycle Stable lifecycle
|
||||
#' @param x a data.frame with antibiotics columns, like `AMX` or `amox`
|
||||
#' @param x a [data.frame] with antibiotics columns, like `AMX` or `amox`. Can be omitted when used inside `dplyr` verbs, such as `filter()`, `mutate()` and `summarise()`.
|
||||
#' @param y,z character vectors to compare
|
||||
#' @inheritParams first_isolate
|
||||
#' @param universal_1,universal_2,universal_3,universal_4,universal_5,universal_6 column names of **broad-spectrum** antibiotics, case-insensitive. See details for which antibiotics will be used at default (which are guessed with [guess_ab_col()]).
|
||||
@ -35,7 +35,10 @@
|
||||
#' @param GramNeg_1,GramNeg_2,GramNeg_3,GramNeg_4,GramNeg_5,GramNeg_6 column names of antibiotics for **Gram-negatives**, case-insensitive. See details for which antibiotics will be used at default (which are guessed with [guess_ab_col()]).
|
||||
#' @param warnings give a warning about missing antibiotic columns (they will be ignored)
|
||||
#' @param ... other parameters passed on to functions
|
||||
#' @details The function [key_antibiotics()] returns a character vector with 12 antibiotic results for every isolate. These isolates can then be compared using [key_antibiotics_equal()], to check if two isolates have generally the same antibiogram. Missing and invalid values are replaced with a dot (`"."`) by [key_antibiotics()] and ignored by [key_antibiotics_equal()].
|
||||
#' @details
|
||||
#' The [key_antibiotics()] function is context-aware when used inside `dplyr` verbs, such as `filter()`, `mutate()` and `summarise()`. This means that then the `x` parameter can be omitted, please see *Examples*.
|
||||
#'
|
||||
#' The function [key_antibiotics()] returns a character vector with 12 antibiotic results for every isolate. These isolates can then be compared using [key_antibiotics_equal()], to check if two isolates have generally the same antibiogram. Missing and invalid values are replaced with a dot (`"."`) by [key_antibiotics()] and ignored by [key_antibiotics_equal()].
|
||||
#'
|
||||
#' The [first_isolate()] function only uses this function on the same microbial species from the same patient. Using this, e.g. an MRSA will be included after a susceptible *S. aureus* (MSSA) is found within the same patient episode. Without key antibiotic comparison it would not. See [first_isolate()] for more info.
|
||||
#'
|
||||
@ -77,30 +80,30 @@
|
||||
#' # `example_isolates` is a dataset available in the AMR package.
|
||||
#' # See ?example_isolates.
|
||||
#'
|
||||
#' # output of the `key_antibiotics` function could be like this:
|
||||
#' # output of the `key_antibiotics()` function could be like this:
|
||||
#' strainA <- "SSSRR.S.R..S"
|
||||
#' strainB <- "SSSIRSSSRSSS"
|
||||
#'
|
||||
#' # can those strings can be compared with:
|
||||
#' # those strings can be compared with:
|
||||
#' key_antibiotics_equal(strainA, strainB)
|
||||
#' # TRUE, because I is ignored (as well as missing values)
|
||||
#'
|
||||
#' key_antibiotics_equal(strainA, strainB, ignore_I = FALSE)
|
||||
#' # FALSE, because I is not ignored and so the 4th value differs
|
||||
#' # FALSE, because I is not ignored and so the 4th character differs
|
||||
#'
|
||||
#' \donttest{
|
||||
#' if (require("dplyr")) {
|
||||
#' # set key antibiotics to a new variable
|
||||
#' my_patients <- example_isolates %>%
|
||||
#' mutate(keyab = key_antibiotics(.)) %>%
|
||||
#' mutate(keyab = key_antibiotics()) %>% # no need to define `x`
|
||||
#' mutate(
|
||||
#' # now calculate first isolates
|
||||
#' first_regular = first_isolate(., col_keyantibiotics = FALSE),
|
||||
#' first_regular = first_isolate(col_keyantibiotics = FALSE),
|
||||
#' # and first WEIGHTED isolates
|
||||
#' first_weighted = first_isolate(., col_keyantibiotics = "keyab")
|
||||
#' first_weighted = first_isolate(col_keyantibiotics = "keyab")
|
||||
#' )
|
||||
#'
|
||||
#' # Check the difference, in this data set it results in 7% more isolates:
|
||||
#' # Check the difference, in this data set it results in a lot more isolates:
|
||||
#' sum(my_patients$first_regular, na.rm = TRUE)
|
||||
#' sum(my_patients$first_weighted, na.rm = TRUE)
|
||||
#' }
|
||||
@ -127,6 +130,9 @@ key_antibiotics <- function(x,
|
||||
GramNeg_6 = guess_ab_col(x, "meropenem"),
|
||||
warnings = TRUE,
|
||||
...) {
|
||||
if (missing(x)) {
|
||||
x <- get_current_data(arg_name = "x", call = -2)
|
||||
}
|
||||
meet_criteria(x, allow_class = "data.frame")
|
||||
meet_criteria(col_mo, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
|
||||
meet_criteria(universal_1, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
|
||||
|
2
R/like.R
2
R/like.R
@ -75,7 +75,7 @@ like <- function(x, pattern, ignore.case = TRUE) {
|
||||
# set to fixed if no regex found
|
||||
fixed <- !any(is_possibly_regex(pattern))
|
||||
if (ignore.case == TRUE) {
|
||||
# set here, otherwise if fixed = TRUE, this warning will be thrown: argument 'ignore.case = TRUE' will be ignored
|
||||
# set here, otherwise if fixed = TRUE, this warning will be thrown: argument `ignore.case = TRUE` will be ignored
|
||||
x <- tolower(x)
|
||||
pattern <- tolower(pattern)
|
||||
}
|
||||
|
84
R/mdro.R
84
R/mdro.R
@ -27,6 +27,7 @@
|
||||
#'
|
||||
#' Determine which isolates are multidrug-resistant organisms (MDRO) according to international and national guidelines.
|
||||
#' @inheritSection lifecycle Stable lifecycle
|
||||
#' @param x a [data.frame] with antibiotics columns, like `AMX` or `amox`. Can be omitted when used inside `dplyr` verbs, such as `filter()`, `mutate()` and `summarise()`.
|
||||
#' @param guideline a specific guideline to follow. When left empty, the publication by Magiorakos *et al.* (2012, Clinical Microbiology and Infection) will be followed, please see *Details*.
|
||||
#' @inheritParams eucast_rules
|
||||
#' @param pct_required_classes minimal required percentage of antimicrobial classes that must be available per isolate, rounded down. For example, with the default guideline, 17 antimicrobial classes must be available for *S. aureus*. Setting this `pct_required_classes` argument to `0.5` (default) means that for every *S. aureus* isolate at least 8 different classes must be available. Any lower number of available classes will return `NA` for that isolate.
|
||||
@ -34,23 +35,36 @@
|
||||
#' @param verbose a logical to turn Verbose mode on and off (default is off). In Verbose mode, the function does not return the MDRO results, but instead returns a data set in logbook form with extensive info about which isolates would be MDRO-positive, or why they are not.
|
||||
#' @inheritSection eucast_rules Antibiotics
|
||||
#' @details
|
||||
#' These functions are context-aware when used inside `dplyr` verbs, such as `filter()`, `mutate()` and `summarise()`. This means that then the `x` parameter can be omitted, please see *Examples*.
|
||||
#'
|
||||
#' For the `pct_required_classes` argument, values above 1 will be divided by 100. This is to support both fractions (`0.75` or `3/4`) and percentages (`75`).
|
||||
#'
|
||||
#' Currently supported guidelines are (case-insensitive):
|
||||
#'
|
||||
#' - `guideline = "CMI2012"`\cr
|
||||
#' Magiorakos AP, Srinivasan A *et al.* "Multidrug-resistant, extensively drug-resistant and pandrug-resistant bacteria: an international expert proposal for interim standard definitions for acquired resistance." Clinical Microbiology and Infection (2012) ([link](https://www.clinicalmicrobiologyandinfection.com/article/S1198-743X(14)61632-3/fulltext))
|
||||
#' - `guideline = "EUCAST3.2"` (or simply `guideline = "EUCAST"`)\cr
|
||||
#' The European international guideline - EUCAST Expert Rules Version 3.2 "Intrinsic Resistance and Unusual Phenotypes" ([link](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/2020/Intrinsic_Resistance_and_Unusual_Phenotypes_Tables_v3.2_20200225.pdf))
|
||||
#' - `guideline = "EUCAST3.1"`\cr
|
||||
#' The European international guideline - EUCAST Expert Rules Version 3.1 "Intrinsic Resistance and Exceptional Phenotypes Tables" ([link](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/Expert_rules_intrinsic_exceptional_V3.1.pdf))
|
||||
#' - `guideline = "TB"`\cr
|
||||
#' The international guideline for multi-drug resistant tuberculosis - World Health Organization "Companion handbook to the WHO guidelines for the programmatic management of drug-resistant tuberculosis" ([link](https://www.who.int/tb/publications/pmdt_companionhandbook/en/))
|
||||
#' - `guideline = "MRGN"`\cr
|
||||
#' The German national guideline - Mueller et al. (2015) Antimicrobial Resistance and Infection Control 4:7. DOI: 10.1186/s13756-015-0047-6
|
||||
#' - `guideline = "BRMO"`\cr
|
||||
#' The Dutch national guideline - Rijksinstituut voor Volksgezondheid en Milieu "WIP-richtlijn BRMO (Bijzonder Resistente Micro-Organismen) (ZKH)" ([link](https://www.rivm.nl/wip-richtlijn-brmo-bijzonder-resistente-micro-organismen-zkh))
|
||||
#' * `guideline = "CMI2012"` (default)
|
||||
#'
|
||||
#' Magiorakos AP, Srinivasan A *et al.* "Multidrug-resistant, extensively drug-resistant and pandrug-resistant bacteria: an international expert proposal for interim standard definitions for acquired resistance." Clinical Microbiology and Infection (2012) ([link](https://www.clinicalmicrobiologyandinfection.com/article/S1198-743X(14)61632-3/fulltext))
|
||||
#'
|
||||
#' * `guideline = "EUCAST3.2"` (or simply `guideline = "EUCAST"`)
|
||||
#'
|
||||
#' The European international guideline - EUCAST Expert Rules Version 3.2 "Intrinsic Resistance and Unusual Phenotypes" ([link](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/2020/Intrinsic_Resistance_and_Unusual_Phenotypes_Tables_v3.2_20200225.pdf))
|
||||
#'
|
||||
#' * `guideline = "EUCAST3.1"`
|
||||
#'
|
||||
#' The European international guideline - EUCAST Expert Rules Version 3.1 "Intrinsic Resistance and Exceptional Phenotypes Tables" ([link](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/Expert_rules_intrinsic_exceptional_V3.1.pdf))
|
||||
#'
|
||||
#' * `guideline = "TB"`
|
||||
#'
|
||||
#' The international guideline for multi-drug resistant tuberculosis - World Health Organization "Companion handbook to the WHO guidelines for the programmatic management of drug-resistant tuberculosis" ([link](https://www.who.int/tb/publications/pmdt_companionhandbook/en/))
|
||||
#'
|
||||
#' * `guideline = "MRGN"`
|
||||
#'
|
||||
#' The German national guideline - Mueller et al. (2015) Antimicrobial Resistance and Infection Control 4:7. DOI: 10.1186/s13756-015-0047-6
|
||||
#'
|
||||
#' * `guideline = "BRMO"`
|
||||
#'
|
||||
#' The Dutch national guideline - Rijksinstituut voor Volksgezondheid en Milieu "WIP-richtlijn BRMO (Bijzonder Resistente Micro-Organismen) (ZKH)" ([link](https://www.rivm.nl/wip-richtlijn-brmo-bijzonder-resistente-micro-organismen-zkh))
|
||||
#'
|
||||
#' Please suggest your own (country-specific) guidelines by letting us know: <https://github.com/msberends/AMR/issues/new>.
|
||||
#'
|
||||
#' **Note:** Every test that involves the Enterobacteriaceae family, will internally be performed using its newly named *order* Enterobacterales, since the Enterobacteriaceae family has been taxonomically reclassified by Adeolu *et al.* in 2016. Before that, Enterobacteriaceae was the only family under the Enterobacteriales (with an i) order. All species under the old Enterobacteriaceae family are still under the new Enterobacterales (without an i) order, but divided into multiple families. The way tests are performed now by this [mdro()] function makes sure that results from before 2016 and after 2016 are identical.
|
||||
@ -79,10 +93,12 @@
|
||||
#' mdro() %>%
|
||||
#' table()
|
||||
#'
|
||||
#' # no need to define `x` when used inside dplyr verbs:
|
||||
#' example_isolates %>%
|
||||
#' mutate(EUCAST = eucast_exceptional_phenotypes(.),
|
||||
#' BRMO = brmo(.),
|
||||
#' MRGN = mrgn(.))
|
||||
#' mutate(MDRO = mdro(),
|
||||
#' EUCAST = eucast_exceptional_phenotypes(),
|
||||
#' BRMO = brmo(),
|
||||
#' MRGN = mrgn())
|
||||
#' }
|
||||
#' }
|
||||
mdro <- function(x,
|
||||
@ -93,6 +109,9 @@ mdro <- function(x,
|
||||
combine_SI = TRUE,
|
||||
verbose = FALSE,
|
||||
...) {
|
||||
if (missing(x)) {
|
||||
x <- get_current_data(arg_name = "x", call = -2)
|
||||
}
|
||||
meet_criteria(x, allow_class = "data.frame")
|
||||
meet_criteria(guideline, allow_class = "character", has_length = 1, allow_NULL = TRUE)
|
||||
meet_criteria(col_mo, allow_class = "character", has_length = 1, is_in = colnames(x), allow_NULL = TRUE)
|
||||
@ -175,24 +194,28 @@ mdro <- function(x,
|
||||
guideline$author <- "Magiorakos AP, Srinivasan A, Carey RB, ..., Vatopoulos A, Weber JT, Monnet DL"
|
||||
guideline$version <- "N/A"
|
||||
guideline$source <- "Clinical Microbiology and Infection 18:3, 2012. DOI: 10.1111/j.1469-0691.2011.03570.x"
|
||||
|
||||
} else if (guideline$code == "eucast3.2") {
|
||||
guideline$name <- "EUCAST Expert Rules, \"Intrinsic Resistance and Unusual Phenotypes\""
|
||||
guideline$author <- "EUCAST (European Committee on Antimicrobial Susceptibility Testing)"
|
||||
guideline$version <- "3.2, 2020"
|
||||
guideline$source <- "https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/2020/Intrinsic_Resistance_and_Unusual_Phenotypes_Tables_v3.2_20200225.pdf"
|
||||
guideline$type <- "MDRs/XDRs/PDRs"
|
||||
|
||||
} else if (guideline$code == "eucast3.1") {
|
||||
guideline$name <- "EUCAST Expert Rules, \"Intrinsic Resistance and Exceptional Phenotypes Tables\""
|
||||
guideline$author <- "EUCAST (European Committee on Antimicrobial Susceptibility Testing)"
|
||||
guideline$version <- "3.1, 2016"
|
||||
guideline$source <- "https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/Expert_rules_intrinsic_exceptional_V3.1.pdf"
|
||||
guideline$type <- "EUCAST Exceptional Phenotypes"
|
||||
|
||||
} else if (guideline$code == "eucast3.2") {
|
||||
guideline$name <- "EUCAST Expert Rules, \"Intrinsic Resistance and Unusual Phenotypes\""
|
||||
guideline$author <- "EUCAST (European Committee on Antimicrobial Susceptibility Testing)"
|
||||
guideline$version <- "3.2, 2020"
|
||||
guideline$source <- "https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/2020/Intrinsic_Resistance_and_Unusual_Phenotypes_Tables_v3.2_20200225.pdf"
|
||||
guideline$type <- "EUCAST Unusual Phenotypes"
|
||||
|
||||
} else if (guideline$code == "tb") {
|
||||
guideline$name <- "Companion handbook to the WHO guidelines for the programmatic management of drug-resistant tuberculosis"
|
||||
guideline$author <- "WHO (World Health Organization)"
|
||||
guideline$version <- "WHO/HTM/TB/2014.11, 2014"
|
||||
guideline$source <- "https://www.who.int/tb/publications/pmdt_companionhandbook/en/"
|
||||
guideline$type <- "MDR-TB's"
|
||||
|
||||
# support per country:
|
||||
} else if (guideline$code == "mrgn") {
|
||||
@ -200,12 +223,14 @@ mdro <- function(x,
|
||||
guideline$author <- "M\u00fcller J, Voss A, K\u00f6ck R, ..., Kern WV, Wendt C, Friedrich AW"
|
||||
guideline$version <- "N/A"
|
||||
guideline$source <- "Antimicrobial Resistance and Infection Control 4:7, 2015. DOI: 10.1186/s13756-015-0047-6"
|
||||
guideline$type <- "MRGNs"
|
||||
|
||||
} else if (guideline$code == "brmo") {
|
||||
guideline$name <- "WIP-Richtlijn Bijzonder Resistente Micro-organismen (BRMO)"
|
||||
guideline$author <- "RIVM (Rijksinstituut voor de Volksgezondheid)"
|
||||
guideline$version <- "Revision as of December 2017"
|
||||
guideline$source <- "https://www.rivm.nl/Documenten_en_publicaties/Professioneel_Praktisch/Richtlijnen/Infectieziekten/WIP_Richtlijnen/WIP_Richtlijnen/Ziekenhuizen/WIP_richtlijn_BRMO_Bijzonder_Resistente_Micro_Organismen_ZKH"
|
||||
guideline$type <- "BRMOs"
|
||||
} else {
|
||||
stop("This guideline is currently unsupported: ", guideline$code, call. = FALSE)
|
||||
}
|
||||
@ -1194,7 +1219,7 @@ mdro <- function(x,
|
||||
if (sum(!is.na(x$MDRO) == 0)) {
|
||||
cat(font_bold(paste0("=> Found 0 MDROs since no isolates are covered by the guideline")))
|
||||
} else {
|
||||
cat(font_bold(paste0("=> Found ", sum(x$MDRO %in% c(2:5), na.rm = TRUE), " MDROs out of ", sum(!is.na(x$MDRO)),
|
||||
cat(font_bold(paste0("=> Found ", sum(x$MDRO %in% c(2:5), na.rm = TRUE), " ", guideline$type, " out of ", sum(!is.na(x$MDRO)),
|
||||
" isolates (", trimws(percentage(sum(x$MDRO %in% c(2:5), na.rm = TRUE) / sum(!is.na(x$MDRO)))), ")\n")))
|
||||
}
|
||||
}
|
||||
@ -1255,6 +1280,9 @@ mdro <- function(x,
|
||||
#' @rdname mdro
|
||||
#' @export
|
||||
brmo <- function(x, guideline = "BRMO", ...) {
|
||||
if (missing(x)) {
|
||||
x <- get_current_data(arg_name = "x", call = -2)
|
||||
}
|
||||
meet_criteria(x, allow_class = "data.frame")
|
||||
meet_criteria(guideline, allow_class = "character", has_length = 1)
|
||||
mdro(x, guideline = "BRMO", ...)
|
||||
@ -1263,6 +1291,9 @@ brmo <- function(x, guideline = "BRMO", ...) {
|
||||
#' @rdname mdro
|
||||
#' @export
|
||||
mrgn <- function(x, guideline = "MRGN", ...) {
|
||||
if (missing(x)) {
|
||||
x <- get_current_data(arg_name = "x", call = -2)
|
||||
}
|
||||
meet_criteria(x, allow_class = "data.frame")
|
||||
meet_criteria(guideline, allow_class = "character", has_length = 1)
|
||||
mdro(x = x, guideline = "MRGN", ...)
|
||||
@ -1271,6 +1302,9 @@ mrgn <- function(x, guideline = "MRGN", ...) {
|
||||
#' @rdname mdro
|
||||
#' @export
|
||||
mdr_tb <- function(x, guideline = "TB", ...) {
|
||||
if (missing(x)) {
|
||||
x <- get_current_data(arg_name = "x", call = -2)
|
||||
}
|
||||
meet_criteria(x, allow_class = "data.frame")
|
||||
meet_criteria(guideline, allow_class = "character", has_length = 1)
|
||||
mdro(x = x, guideline = "TB", ...)
|
||||
@ -1279,6 +1313,9 @@ mdr_tb <- function(x, guideline = "TB", ...) {
|
||||
#' @rdname mdro
|
||||
#' @export
|
||||
mdr_cmi2012 <- function(x, guideline = "CMI2012", ...) {
|
||||
if (missing(x)) {
|
||||
x <- get_current_data(arg_name = "x", call = -2)
|
||||
}
|
||||
meet_criteria(x, allow_class = "data.frame")
|
||||
meet_criteria(guideline, allow_class = "character", has_length = 1)
|
||||
mdro(x = x, guideline = "CMI2012", ...)
|
||||
@ -1287,6 +1324,9 @@ mdr_cmi2012 <- function(x, guideline = "CMI2012", ...) {
|
||||
#' @rdname mdro
|
||||
#' @export
|
||||
eucast_exceptional_phenotypes <- function(x, guideline = "EUCAST", ...) {
|
||||
if (missing(x)) {
|
||||
x <- get_current_data(arg_name = "x", call = -2)
|
||||
}
|
||||
meet_criteria(x, allow_class = "data.frame")
|
||||
meet_criteria(guideline, allow_class = "character", has_length = 1)
|
||||
mdro(x = x, guideline = "EUCAST", ...)
|
||||
|
@ -372,11 +372,9 @@ mo_is_intrinsic_resistant <- function(x, ab, language = get_locale(), ...) {
|
||||
meet_criteria(ab, allow_NA = FALSE)
|
||||
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
|
||||
|
||||
x.mo <- as.mo(x, language = language, ...)
|
||||
x <- mo_name(x.mo, language = NULL) # has to match intrinsic_resistant$microorganism
|
||||
ab <- ab_name(ab, language = NULL, # has to match intrinsic_resistant$antibiotic
|
||||
flag_multiple_results = FALSE,
|
||||
info = FALSE)
|
||||
x <- as.mo(x, language = language, ...)
|
||||
ab <- as.ab(ab, language = NULL, flag_multiple_results = FALSE, info = FALSE)
|
||||
|
||||
if (length(x) == 1 & length(ab) > 1) {
|
||||
x <- rep(x, length(ab))
|
||||
} else if (length(ab) == 1 & length(x) > 1) {
|
||||
@ -389,15 +387,13 @@ mo_is_intrinsic_resistant <- function(x, ab, language = get_locale(), ...) {
|
||||
# show used version number once per session
|
||||
if (is.null(getOption("AMR_intrinsic_resistance_note", NULL))) {
|
||||
message_("Determining intrinsic resistance based on ",
|
||||
AMR:::format_eucast_version_nr(3.2, FALSE), ". ",
|
||||
font_bold("This message is shown once per session."))
|
||||
format_eucast_version_nr(3.2, FALSE), ". ",
|
||||
font_bold("This note is shown only once per session."))
|
||||
options(AMR_intrinsic_resistance_note = "shown")
|
||||
}
|
||||
|
||||
# this saves about 50% in calculation time
|
||||
intrinsic_to_check <- intrinsic_resistant[which(intrinsic_resistant$microorganism %in% x |
|
||||
intrinsic_resistant$antibiotic %in% ab), , drop = FALSE]
|
||||
paste(x, ab) %in% paste(intrinsic_to_check$microorganism, intrinsic_to_check$antibiotic)
|
||||
# runs against internal vector: INTRINSIC_R (see zzz.R)
|
||||
paste(x, ab) %in% INTRINSIC_R
|
||||
}
|
||||
|
||||
#' @rdname mo_property
|
||||
@ -616,23 +612,17 @@ mo_validate <- function(x, property, language, ...) {
|
||||
}
|
||||
|
||||
find_mo_col <- function(fn) {
|
||||
# this function tries to find an mo column using dplyr:::peek_mask() for mo_is_*() functions,
|
||||
# this function tries to find an mo column using dplyr::cur_data_all() for mo_is_*() functions,
|
||||
# which is useful when functions are used within dplyr verbs
|
||||
peek_mask_dplyr <- import_fn("peek_mask", "dplyr", error_on_fail = FALSE)
|
||||
if (!is.null(peek_mask_dplyr)) {
|
||||
df <- NULL
|
||||
mo <- NULL
|
||||
try({
|
||||
df <- as.data.frame(peek_mask_dplyr()$across_cols(), stringsAsFactors = FALSE)
|
||||
mo <- suppressMessages(search_type_in_df(df, "mo"))
|
||||
}, silent = TRUE)
|
||||
if (!is.null(df) && !is.null(mo) && is.data.frame(df)) {
|
||||
message_("Using column '", font_bold(mo), "' as input for ", fn, "()")
|
||||
return(df[, mo, drop = TRUE])
|
||||
} else {
|
||||
stop_("Argument `x` is missing and no column with info about microorganisms could be found.", call = -2)
|
||||
}
|
||||
df <- get_current_data("x", call = -3) # will return an error if not found
|
||||
mo <- NULL
|
||||
try({
|
||||
mo <- suppressMessages(search_type_in_df(df, "mo"))
|
||||
}, silent = TRUE)
|
||||
if (!is.null(df) && !is.null(mo) && is.data.frame(df)) {
|
||||
message_("Using column '", font_bold(mo), "' as input for ", fn, "()")
|
||||
return(df[, mo, drop = TRUE])
|
||||
} else {
|
||||
stop_("Argument `x` is missing.", call = -2)
|
||||
stop_("argument `x` is missing and no column with info about microorganisms could be found.", call = -2)
|
||||
}
|
||||
}
|
||||
|
28
R/rsi.R
28
R/rsi.R
@ -354,7 +354,7 @@ as.rsi.mic <- function(x,
|
||||
uti <- rep(uti, length(x))
|
||||
}
|
||||
|
||||
message_("=> Interpreting MIC values of `", font_bold(ab), "` (",
|
||||
message_("=> Interpreting MIC values of '", font_bold(ab), "' (",
|
||||
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
|
||||
ab_name(ab_coerced, tolower = TRUE), ")", mo_var_found,
|
||||
" according to ", ifelse(identical(reference_data, AMR::rsi_translation),
|
||||
@ -444,7 +444,7 @@ as.rsi.disk <- function(x,
|
||||
uti <- rep(uti, length(x))
|
||||
}
|
||||
|
||||
message_("=> Interpreting disk zones of `", font_bold(ab), "` (",
|
||||
message_("=> Interpreting disk zones of '", font_bold(ab), "' (",
|
||||
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
|
||||
ab_name(ab_coerced, tolower = TRUE), ")", mo_var_found,
|
||||
" according to ", ifelse(identical(reference_data, AMR::rsi_translation),
|
||||
@ -720,22 +720,23 @@ exec_as.rsi <- function(method,
|
||||
lookup_other <- paste(mo_other, ab)
|
||||
|
||||
if (all(trans$uti == TRUE, na.rm = TRUE) & all(uti == FALSE)) {
|
||||
message_("WARNING.", add_fn = list(font_red, font_bold), as_note = FALSE)
|
||||
message_("WARNING.", add_fn = list(font_yellow, font_bold), as_note = FALSE)
|
||||
warning_("Interpretation of ", font_bold(ab_name(ab, tolower = TRUE)), " for some microorganisms is only available for (uncomplicated) urinary tract infections (UTI). Use parameter 'uti' to set which isolates are from urine. See ?as.rsi.", call = FALSE)
|
||||
warned <- TRUE
|
||||
}
|
||||
|
||||
any_is_intrinsic_resistant <- FALSE
|
||||
|
||||
for (i in seq_len(length(x))) {
|
||||
if (isTRUE(add_intrinsic_resistance)) {
|
||||
is_intrinsic_r <- paste(mo[i], ab) %in% INTRINSIC_R
|
||||
any_is_intrinsic_resistant <- any_is_intrinsic_resistant | is_intrinsic_r
|
||||
|
||||
if (isTRUE(add_intrinsic_resistance) & is_intrinsic_r) {
|
||||
if (!guideline_coerced %like% "EUCAST") {
|
||||
warning_("Using 'add_intrinsic_resistance' is only useful when using EUCAST guidelines, since the rules for intrinsic resistance are based on EUCAST.", call = FALSE)
|
||||
} else {
|
||||
get_record <- subset(intrinsic_resistant,
|
||||
microorganism == mo_name(mo[i], language = NULL) & antibiotic == ab_name(ab, language = NULL))
|
||||
if (nrow(get_record) > 0) {
|
||||
new_rsi[i] <- "R"
|
||||
next
|
||||
}
|
||||
new_rsi[i] <- "R"
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,6 +796,13 @@ exec_as.rsi <- function(method,
|
||||
}
|
||||
}
|
||||
|
||||
if (any_is_intrinsic_resistant & guideline_coerced %like% "EUCAST" & !isTRUE(add_intrinsic_resistance)) {
|
||||
# found some intrinsic resistance, but was not applied
|
||||
message_("WARNING.", add_fn = list(font_yellow, font_bold), as_note = FALSE)
|
||||
warning_("Found intrinsic resistance in some bug/drug combinations, although it was not applied.\nUse `as.rsi(..., add_intrinsic_resistance = TRUE)` to apply it.", call = FALSE)
|
||||
warned <- TRUE
|
||||
}
|
||||
|
||||
new_rsi <- x_bak %pm>%
|
||||
pm_left_join(data.frame(x_mo = paste0(df$x, df$mo), new_rsi,
|
||||
stringsAsFactors = FALSE),
|
||||
|
10
R/zzz.R
10
R/zzz.R
@ -36,6 +36,10 @@
|
||||
value = create_MO.old_lookup(),
|
||||
envir = asNamespace("AMR"))
|
||||
|
||||
assign(x = "INTRINSIC_R",
|
||||
value = create_intr_resistance(),
|
||||
envir = asNamespace("AMR"))
|
||||
|
||||
assign(x = "LANGUAGES_SUPPORTED",
|
||||
value = sort(c("en", unique(translations_file$lang))),
|
||||
envir = asNamespace("AMR"))
|
||||
@ -86,6 +90,12 @@
|
||||
font_bold("options(AMR_silentstart = TRUE)"), "]"))
|
||||
}
|
||||
|
||||
create_intr_resistance <- function() {
|
||||
# for mo_is_intrinsic_resistant() - saves a lot of time when executed on this vector
|
||||
paste(AMR::microorganisms[match(AMR::intrinsic_resistant$microorganism, AMR::microorganisms$fullname), "mo", drop = TRUE],
|
||||
AMR::antibiotics[match(AMR::intrinsic_resistant$antibiotic, AMR::antibiotics$name), "ab", drop = TRUE])
|
||||
}
|
||||
|
||||
create_species_cons_cops <- function(type = c("CoNS", "CoPS")) {
|
||||
# Determination of which staphylococcal species are CoNS/CoPS according to:
|
||||
# - Becker et al. 2014, PMID 25278577
|
||||
|
Reference in New Issue
Block a user