1
0
mirror of https://github.com/msberends/AMR.git synced 2024-12-25 07:26:12 +01:00

(v1.6.0.9010) big first_isolate() update

This commit is contained in:
dr. M.S. (Matthijs) Berends 2021-04-26 23:57:37 +02:00
parent 5f9e7bd3ee
commit 93683a4ae2
38 changed files with 1134 additions and 933 deletions

View File

@ -1,6 +1,6 @@
Package: AMR
Version: 1.6.0.9009
Date: 2021-04-23
Version: 1.6.0.9010
Date: 2021-04-26
Title: Antimicrobial Resistance Data Analysis
Authors@R: c(
person(role = c("aut", "cre"),

View File

@ -161,8 +161,10 @@ export(ab_tradenames)
export(ab_url)
export(age)
export(age_groups)
export(all_antimicrobials)
export(aminoglycosides)
export(anti_join_microorganisms)
export(antimicrobials_equal)
export(as.ab)
export(as.disk)
export(as.mic)
@ -237,6 +239,7 @@ export(is.rsi.eligible)
export(is_new_episode)
export(key_antibiotics)
export(key_antibiotics_equal)
export(key_antimicrobials)
export(kurtosis)
export(labels_rsi_count)
export(left_join_microorganisms)

16
NEWS.md
View File

@ -1,8 +1,16 @@
# AMR 1.6.0.9009
## <small>Last updated: 23 April 2021</small>
# AMR 1.6.0.9010
## <small>Last updated: 26 April 2021</small>
### New
* Function `custom_eucast_rules()` that brings support for custom AMR rules in `eucast_rules()`
* Support for all four methods to determine first isolates as summarised by Hindler *et al* (doi: [10.1086/511864](https://doi.org/10.1086/511864)): isolate-based, patient-based, episode-based and phenotype-based. The last method is now the default.
* Since fungal isolates can also be selected, new functions `key_antimicrobials()` and `all_antimicrobials()` have replaced the now deprecated function `key_antibiotics()`
* Using `key_antimicrobials()` still only selects six preferred antibiotics for Gram-negatives, six for Gram-positives, and six universal antibiotics. It has a new `antifungal` argument to set antifungal agents (antimycotics).
* The `first_isolate()` function gained the argument `method` that has to be "phenotype-based", "episode-based", "patient-based", or "isolate-based". The old behaviour is equal to "episode-based", while the new default is "phenotype-based".
* Using `type == "points"` in the `first_isolate()` function for phenotype-based selection will now consider all antimicrobial drugs in the data set, using the new `all_antimicrobials()`
* The `first_isolate()` function can now take a vector of values for `col_keyantibiotics` and can have an episode length of `Inf`
* The `filter_first_isolate()` function has not changed, as it uses the episode-based method. The `filter_first_weighted_isolate()` may now include more isolates as uses the phenotype-based method.
* The documentation of the `first_isolate()` and `key_antimicrobials()` functions has been completely rewritten.
### Changed
* Custom MDRO guidelines (`mdro()`, `custom_mdro_guideline()`):
@ -12,7 +20,6 @@
* The `example_isolates` data set now contains some (fictitious) zero-year old patients
* Fix for minor translation errors
* Printing of microbial codes in a `data.frame` or `tibble` now gives a warning if the data contains old microbial codes (from a previous AMR package version)
* `first_isolate()` can now take a vector of values for `col_keyantibiotics` and can have an episode length of `Inf`
* Extended the `like()` functions:
* Now checks if `pattern` is a *valid* regular expression
* Added `%unlike%` and `%unlike_case%` (as negations of the existing `%like%` and `%like_case%`). This greatly improves readability:
@ -25,9 +32,6 @@
* Fixed an installation error on R-3.0
* Added `info` argument to `as.mo()` to turn on/off the progress bar
* Fixed a bug that `col_mo` for some functions (esp. `eucast_rules()` and `mdro()`) could not be column names of the `microorganisms` data set as it would throw an error
* Using `first_isolate()` with key antibiotics:
* Fixed a bug in the algorithm when using `type == "points"`, that now leads to inclusion of slightly more isolates
* Big speed improvement for `key_antibiotics_equal()` when using `type == "points"`
# AMR 1.6.0

View File

@ -190,8 +190,8 @@ search_type_in_df <- function(x, type, info = TRUE) {
}
# -- key antibiotics
if (type == "keyantibiotics") {
if (any(colnames(x) %like% "^key.*(ab|antibiotics)")) {
found <- sort(colnames(x)[colnames(x) %like% "^key.*(ab|antibiotics)"])[1]
if (any(colnames(x) %like% "^key.*(ab|antibiotics|antimicrobials)")) {
found <- sort(colnames(x)[colnames(x) %like% "^key.*(ab|antibiotics|antimicrobials)"])[1]
}
}
# -- date
@ -318,7 +318,9 @@ word_wrap <- function(...,
msg <- paste0(c(...), collapse = "")
if (isTRUE(as_note)) {
msg <- paste0("NOTE: ", gsub("^note:? ?", "", msg, ignore.case = TRUE))
# \u2139 is a symbol officially named 'information source'
# \ufe0f can add the blue square around it: \u2139\ufe0f
msg <- paste0("\u2139 ", gsub("^note:? ?", "", msg, ignore.case = TRUE))
}
if (msg %like% "\n") {
@ -352,8 +354,8 @@ word_wrap <- function(...,
msg <- paste0(msg, collapse = " ")
msg <- gsub("\n ", "\n", msg, fixed = TRUE)
if (msg_stripped %like% "^NOTE: ") {
indentation <- 6 + extra_indent
if (msg_stripped %like% "\u2139 ") {
indentation <- 2 + extra_indent
} else if (msg_stripped %like% "^=> ") {
indentation <- 3 + extra_indent
} else {

View File

@ -45,3 +45,71 @@ p_symbol <- function(p, emptychar = " ") {
s
}
#' @name AMR-deprecated
#' @export
key_antibiotics <- function(x = NULL,
col_mo = NULL,
universal_1 = guess_ab_col(x, "amoxicillin"),
universal_2 = guess_ab_col(x, "amoxicillin/clavulanic acid"),
universal_3 = guess_ab_col(x, "cefuroxime"),
universal_4 = guess_ab_col(x, "piperacillin/tazobactam"),
universal_5 = guess_ab_col(x, "ciprofloxacin"),
universal_6 = guess_ab_col(x, "trimethoprim/sulfamethoxazole"),
GramPos_1 = guess_ab_col(x, "vancomycin"),
GramPos_2 = guess_ab_col(x, "teicoplanin"),
GramPos_3 = guess_ab_col(x, "tetracycline"),
GramPos_4 = guess_ab_col(x, "erythromycin"),
GramPos_5 = guess_ab_col(x, "oxacillin"),
GramPos_6 = guess_ab_col(x, "rifampin"),
GramNeg_1 = guess_ab_col(x, "gentamicin"),
GramNeg_2 = guess_ab_col(x, "tobramycin"),
GramNeg_3 = guess_ab_col(x, "colistin"),
GramNeg_4 = guess_ab_col(x, "cefotaxime"),
GramNeg_5 = guess_ab_col(x, "ceftazidime"),
GramNeg_6 = guess_ab_col(x, "meropenem"),
warnings = TRUE,
...) {
.Deprecated(old = "key_antibiotics()",
new = "key_antimicrobials()",
package = "AMR")
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
x <- tryCatch(get_current_data(arg_name = "x", call = -2), error = function(e) x)
}
key_antimicrobials(x = x,
col_mo = col_mo,
universal = c(universal_1, universal_2, universal_3, universal_4, universal_5, universal_6),
gram_negative = c(GramNeg_1, GramNeg_2, GramNeg_3, GramNeg_4, GramNeg_5, GramNeg_6),
gram_positive = c(GramPos_1, GramPos_2, GramPos_3, GramPos_4, GramPos_5, GramPos_6),
antifungal = NULL,
only_rsi_columns = FALSE,
...)
}
#' @name AMR-deprecated
#' @export
key_antibiotics_equal <- function(y,
z,
type = "keyantimicrobials",
ignore_I = TRUE,
points_threshold = 2,
info = FALSE,
na.rm = TRUE,
...) {
.Deprecated(old = "key_antibiotics_equal()",
new = "antimicrobials_equal()",
package = "AMR")
antimicrobials_equal(y = y,
z = z,
type = type,
ignore_I = ignore_I,
points_threshold = points_threshold,
info = info)
}

View File

@ -34,62 +34,91 @@
#' @param col_testcode column name of the test codes. Use `col_testcode = NULL` to **not** exclude certain test codes (such as test codes for screening). In that case `testcodes_exclude` will be ignored.
#' @param col_specimen column name of the specimen type or group
#' @param col_icu column name of the logicals (`TRUE`/`FALSE`) whether a ward or department is an Intensive Care Unit (ICU)
#' @param col_keyantibiotics column name of the key antibiotics to determine first (weighted) isolates, see [key_antibiotics()]. Defaults to the first column that starts with 'key' followed by 'ab' or 'antibiotics' (case insensitive). Use `col_keyantibiotics = FALSE` to prevent this. Can also be the output of [key_antibiotics()].
#' @param col_keyantimicrobials (only useful when `method = "phenotype-based"`) column name of the key antimicrobials to determine first (weighted) isolates, see [key_antimicrobials()]. Defaults to the first column that starts with 'key' followed by 'ab' or 'antibiotics' or 'antimicrobials' (case insensitive). Use `col_keyantimicrobials = FALSE` to prevent this. Can also be the output of [key_antimicrobials()].
#' @param episode_days episode in days after which a genus/species combination will be determined as 'first isolate' again. The default of 365 days is based on the guideline by CLSI, see *Source*.
#' @param testcodes_exclude character vector with test codes that should be excluded (case-insensitive)
#' @param icu_exclude logical to indicate whether ICU isolates should be excluded (rows with value `TRUE` in the column set with `col_icu`)
#' @param specimen_group value in the column set with `col_specimen` to filter on
#' @param type type to determine weighed isolates; can be `"keyantibiotics"` or `"points"`, see *Details*
#' @param ignore_I logical to indicate whether antibiotic interpretations with `"I"` will be ignored when `type = "keyantibiotics"`, see *Details*
#' @param points_threshold points until the comparison of key antibiotics will lead to inclusion of an isolate when `type = "points"`, see *Details*
#' @param type type to determine weighed isolates; can be `"keyantimicrobials"` or `"points"`, see *Details*
#' @param method the algorithm to apply, either `"phenotype-based"`, `"episode-based"`, `"patient-based"` or `"isolate-based"` (can be abbreviated), see *Details*
#' @param ignore_I logical to indicate whether antibiotic interpretations with `"I"` will be ignored when `type = "keyantimicrobials"`, see *Details*
#' @param points_threshold minimum number of points to require before differences in the antibiogram will lead to inclusion of an isolate when `type = "points"`, see *Details*
#' @param info a [logical] to indicate info should be printed, defaults to `TRUE` only in interactive mode
#' @param include_unknown logical to indicate 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 include_untested_rsi logical to indicate whether also rows without antibiotic results are still eligible for becoming a first isolate. Use `include_untested_rsi = FALSE` to always return `FALSE` for such rows. This checks the data set for columns of class `<rsi>` and consequently requires transforming columns with antibiotic results using [as.rsi()] first.
#' @param ... arguments passed on to [first_isolate()] when using [filter_first_isolate()], or arguments passed on to [key_antibiotics()] when using [filter_first_weighted_isolate()]
#' @param ... arguments passed on to [first_isolate()] when using [filter_first_isolate()], or arguments passed on to [key_antimicrobials()] otherwise (such as `universal`, `gram_negative`, `gram_positive`)
#' @details
#' To conduct epidemiological analyses on antimicrobial resistance data, only so-called first isolates should be included to prevent overestimation and underestimation of antimicrobial resistance. Different algorithms can be used to do so, see below.
#'
#' These functions are context-aware. This means that then the `x` argument can be left blank, 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.
#'
#' ## Why this is so Important
#' To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode [(Hindler *et al.* 2007)](https://pubmed.ncbi.nlm.nih.gov/17304462/). If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all *S. aureus* isolates would be overestimated, because you included this MRSA more than once. It would be [selection bias](https://en.wikipedia.org/wiki/Selection_bias).
#'
#' ## `filter_*()` Shortcuts
#'
#' The functions [filter_first_isolate()] and [filter_first_weighted_isolate()] are helper functions to quickly filter on first isolates.
#' ## Different algorithms
#'
#' The function [filter_first_isolate()] is essentially equal to either:
#' According to Hindler *et al.* (2007, \doi{10.1086/511864}), there are different algorithms to select first isolates with increasing reliability: isolate-based, patient-based, episode-based and phenotype-based. All algorithms select on a combination of the taxonomic genus and species (not subspecies).
#'
#' ```
#' x[first_isolate(x, ...), ]
#'
#' x %>% filter(first_isolate(...))
#' ```
#' All mentioned algorithms are covered in the [first_isolate()] function:
#'
#' The function [filter_first_weighted_isolate()] is essentially equal to:
#'
#' ```
#' x %>%
#' mutate(keyab = key_antibiotics(.)) %>%
#' mutate(only_weighted_firsts = first_isolate(x,
#' col_keyantibiotics = "keyab", ...)) %>%
#' filter(only_weighted_firsts == TRUE) %>%
#' select(-only_weighted_firsts, -keyab)
#' ```
#' @section Key Antibiotics:
#' There are two ways to determine whether isolates can be included as first weighted isolates which will give generally the same results:
#'
#' 1. Using `type = "keyantibiotics"` and argument `ignore_I`
#' | **Algorithm** | **Function to apply** |
#' |--------------------------------------------------|-------------------------------------------------------|
#' | Isolate-based | `first_isolate(x, method = "isolate-based")` |
#' | *(= all isolates)* | |
#' | | |
#' | | |
#' | Patient-based | `first_isolate(x, method = "patient-based")` |
#' | *(= first isolate per patient)* | |
#' | | |
#' | | |
#' | Episode-based | `first_isolate(x, method = "episode-based")`, or: |
#' | *(= first isolate per episode)* | |
#' | - 7-Day interval from initial isolate | - `first_isolate(x, method = "e", episode_days = 7)` |
#' | - 30-Day interval from initial isolate | - `first_isolate(x, method = "e", episode_days = 30)` |
#' | | |
#' | | |
#' | Phenotype-based | `first_isolate(x, method = "phenotype-based")`, or: |
#' | *(= first isolate per phenotype)* | |
#' | - Major difference in any antimicrobial result | - `first_isolate(x, type = "points")` |
#' | - Any difference in key antimicrobial results | - `first_isolate(x, type = "keyantimicrobials")` |
#'
#' Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With `ignore_I = FALSE`, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. Read more about this in the [key_antibiotics()] function.
#' ### Isolate-based
#'
#' This algorithm does not require any selection, as all isolates should be included. It does, however, respect all arguments set in the [first_isolate()] function. For example, the default setting for `include_unknown` (`FALSE`) will omit selection of rows without a microbial ID.
#'
#' ### Patient-based
#'
#' To include every genus-species combination per patient once, set the `episode_days` to `Inf`. Although often inappropriate, this algorithm makes sure that no duplicate isolates are selected from the same patient.
#'
#' ### Episode-based
#'
#' To include every genus-species combination per patient episode once, set the `episode_days` to a sensible number of days. Depending on the type of analysis, this could be 14, 30, 60 or 365. Short episodes are common for analysing specific hospital or ward data, long episodes are common for analysing regional and national data.
#'
#' This is the most common algorithm to correct for duplicate isolates. Patients are categorised into episodes based on their ID and dates (e.g., the date of specimen receipt or laboratory result). While this is a common algorithm, it does not take into account antimicrobial test results. This means that e.g. a methicillin-resistant *Staphylococcus aureus* (MRSA) isolate cannot be differentiated from a wildtype *Staphylococcus aureus* isolate.
#'
#' ### Phenotype-based
#'
#' This is a more reliable algorithm, since it also *weighs* the antibiogram (antimicrobial test results) yielding so-called 'first weighted isolates'. There are two different methods to weigh the antibiogram:
#'
#' 1. Using `type = "points"` and argument `points_threshold`
#'
#' This method weighs *all* antimicrobial agents available in the data set. Any difference from I to S or R (or vice versa) counts as 0.5 points, a difference from S to R (or vice versa) counts as 1 point. When the sum of points exceeds `points_threshold`, which defaults to `2`, an isolate will be selected as a first weighted isolate.
#'
#' 2. Using `type = "points"` and argument `points_threshold`
#' All antimicrobials are internally selected using the [all_antimicrobials()] function. The output of this function does not need to be passed to the [first_isolate()] function.
#'
#' A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds `points_threshold`, which defaults to `2`, an isolate will be (re)selected as a first weighted isolate.
#'
#' 2. Using `type = "keyantimicrobials"` and argument `ignore_I`
#'
#' This method only weighs specific antimicrobial agents, called *key antimicrobials*. Any difference from S to R (or vice versa) in these key antimicrobials will select an isolate as a first weighted isolate. With `ignore_I = FALSE`, also differences from I to S or R (or vice versa) will lead to this.
#'
#' Key antimicrobials are internally selected using the [key_antimicrobials()] function, but can also be added manually as a variable to the data and set in the `col_keyantimicrobials` argument. Another option is to pass the output of the [key_antimicrobials()] function directly to the `col_keyantimicrobials` argument.
#'
#'
#' The default algorithm is phenotype-based (using `type = "points"`) and episode-based (using `episode_days = 365`). This makes sure that every genus-species combination is selected per patient once per year, while taking into account all antimicrobial test results.
#' @rdname first_isolate
#' @seealso [key_antibiotics()]
#' @seealso [key_antimicrobials()]
#' @export
#' @return A [`logical`] vector
#' @source Methodology of this function is strictly based on:
@ -101,7 +130,6 @@
#' # See ?example_isolates.
#'
#' example_isolates[first_isolate(example_isolates), ]
#'
#' \donttest{
#' # faster way, only works in R 3.2 and later:
#' example_isolates[first_isolate(), ]
@ -139,7 +167,7 @@
#'
#' # Have a look at A and B.
#' # B is more reliable because every isolate is counted only once.
#' # Gentamicin resistance in hospital D appears to be 3.7% higher than
#' # Gentamicin resistance in hospital D appears to be 4.2% higher than
#' # when you (erroneously) would have used all isolates for analysis.
#' }
#' }
@ -150,18 +178,32 @@ first_isolate <- function(x = NULL,
col_testcode = NULL,
col_specimen = NULL,
col_icu = NULL,
col_keyantibiotics = NULL,
col_keyantimicrobials = NULL,
episode_days = 365,
testcodes_exclude = NULL,
icu_exclude = FALSE,
specimen_group = NULL,
type = "keyantibiotics",
type = "points",
method = c("phenotype-based", "episode-based", "patient-based", "isolate-based"),
ignore_I = TRUE,
points_threshold = 2,
info = interactive(),
include_unknown = FALSE,
include_untested_rsi = TRUE,
...) {
dots <- unlist(list(...))
if (length(dots) != 0) {
# backwards compatibility with old arguments
dots.names <- names(dots)
if ("filter_specimen" %in% dots.names) {
specimen_group <- dots[which(dots.names == "filter_specimen")]
}
if ("col_keyantibiotics" %in% dots.names) {
col_keyantimicrobials <- dots[which(dots.names == "col_keyantibiotics")]
}
}
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
@ -177,15 +219,25 @@ first_isolate <- function(x = NULL,
}
meet_criteria(col_specimen, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_icu, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
if (length(col_keyantibiotics) > 1) {
meet_criteria(col_keyantibiotics, allow_class = "character", has_length = nrow(x))
x$keyabcol <- col_keyantibiotics
col_keyantibiotics <- "keyabcol"
# method
if (missing(method)) {
method <- method[1L]
}
meet_criteria(method, allow_class = "character", has_length = 1, is_in = c("phenotype-based", "episode-based", "patient-based", "isolate-based", "p", "e", "i"))
# key antimicrobials
if (length(col_keyantimicrobials) > 1) {
meet_criteria(col_keyantimicrobials, allow_class = "character", has_length = nrow(x))
x$keyabcol <- col_keyantimicrobials
col_keyantimicrobials <- "keyabcol"
} else {
if (isFALSE(col_keyantibiotics)) {
col_keyantibiotics <- NULL
if (isFALSE(col_keyantimicrobials)) {
col_keyantimicrobials <- NULL
# method cannot be phenotype-based anymore
if (method %in% c("phenotype-based", "p")) {
method <- "episode-based"
}
}
meet_criteria(col_keyantibiotics, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_keyantimicrobials, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
}
meet_criteria(episode_days, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = FALSE)
meet_criteria(testcodes_exclude, allow_class = "character", allow_NULL = TRUE)
@ -198,21 +250,23 @@ first_isolate <- function(x = NULL,
meet_criteria(include_unknown, allow_class = "logical", has_length = 1)
meet_criteria(include_untested_rsi, allow_class = "logical", has_length = 1)
method[method == "p"] <- "phenotype-based"
method[method == "e"] <- "episode-based"
method[method == "i"] <- "isolate-based"
if (info == TRUE) {
message_(paste0("Determining first isolates using the '", font_bold(method), "' method",
ifelse(method %in% c("episode-based", "phenotype-based"),
ifelse(is.infinite(episode_days),
" without a specified episode length",
paste(" and an episode length of", episode_days, "days")),
"")),
as_note = FALSE,
add_fn = font_black)
}
# remove data.table, grouping from tibbles, etc.
x <- as.data.frame(x, stringsAsFactors = FALSE)
dots <- unlist(list(...))
if (length(dots) != 0) {
# backwards compatibility with old arguments
dots.names <- names(dots)
if ("filter_specimen" %in% dots.names) {
specimen_group <- dots[which(dots.names == "filter_specimen")]
}
if ("tbl" %in% dots.names) {
x <- dots[which(dots.names == "tbl")]
}
}
# try to find columns based on type
# -- mo
if (is.null(col_mo)) {
@ -220,6 +274,37 @@ first_isolate <- function(x = NULL,
stop_if(is.null(col_mo), "`col_mo` must be set")
}
# methods ----
if (method == "isolate-based") {
episode_days <- Inf
col_keyantimicrobials <- NULL
x$dummy_dates <- Sys.Date()
col_date <- "dummy_dates"
x$dummy_patients <- paste("dummy", seq_len(nrow(x))) # all 'patients' must be unique
col_patient_id <- "dummy_patients"
} else if (method == "patient-based") {
episode_days <- Inf
col_keyantimicrobials <- NULL
} else if (method == "episode-based") {
col_keyantimicrobials <- NULL
} else if (method == "phenotype-based") {
if (missing(type) & !is.null(col_keyantimicrobials)) {
# type = "points" is default, but not set explicitly, while col_keyantimicrobials is
type <- "keyantimicrobials"
}
if (type == "points") {
x$keyantimicrobials <- all_antimicrobials(x, only_rsi_columns = FALSE)
col_keyantimicrobials <- "keyantimicrobials"
} else if (type == "keyantimicrobials" & is.null(col_keyantimicrobials)) {
col_keyantimicrobials <- search_type_in_df(x = x, type = "keyantibiotics")
if (is.null(col_keyantimicrobials)) {
# still not found as a column, create it ourselves
x$keyantimicrobials <- key_antimicrobials(x, only_rsi_columns = FALSE, col_mo = col_mo, ...)
col_keyantimicrobials <- "keyantimicrobials"
}
}
}
# -- date
if (is.null(col_date)) {
col_date <- search_type_in_df(x = x, type = "date")
@ -238,11 +323,6 @@ first_isolate <- function(x = NULL,
}
stop_if(is.null(col_patient_id), "`col_patient_id` must be set")
}
# -- key antibiotics
if (is.null(col_keyantibiotics)) {
col_keyantibiotics <- search_type_in_df(x = x, type = "keyantibiotics")
}
# -- specimen
if (is.null(col_specimen) & !is.null(specimen_group)) {
@ -262,7 +342,7 @@ first_isolate <- function(x = NULL,
check_columns_existance(col_mo)
check_columns_existance(col_testcode)
check_columns_existance(col_icu)
check_columns_existance(col_keyantibiotics)
check_columns_existance(col_keyantimicrobials)
# convert dates to Date
dates <- as.Date(x[, col_date, drop = TRUE])
@ -281,7 +361,7 @@ first_isolate <- function(x = NULL,
}
# remove testcodes
if (!is.null(testcodes_exclude) & info == TRUE) {
message_("[Criterion] Exclude test codes: ", toString(paste0("'", testcodes_exclude, "'")),
message_("Excluding test codes: ", toString(paste0("'", testcodes_exclude, "'")),
add_fn = font_black,
as_note = FALSE)
}
@ -294,13 +374,13 @@ first_isolate <- function(x = NULL,
if (!is.null(specimen_group)) {
check_columns_existance(col_specimen, x)
if (info == TRUE) {
message_("[Criterion] Exclude other than specimen group '", specimen_group, "'",
message_("Excluding other than specimen group '", specimen_group, "'",
add_fn = font_black,
as_note = FALSE)
}
}
if (!is.null(col_keyantibiotics)) {
x$newvar_key_ab <- x[, col_keyantibiotics, drop = TRUE]
if (!is.null(col_keyantimicrobials)) {
x$newvar_key_ab <- x[, col_keyantimicrobials, drop = TRUE]
}
if (is.null(testcodes_exclude)) {
@ -341,7 +421,7 @@ first_isolate <- function(x = NULL,
}
if (row.start == row.end) {
if (info == TRUE) {
message_("=> Found ", font_bold("1 isolate"), ", as the data only contained 1 row",
message_("=> Found ", font_bold("1 first isolate"), ", as the data only contained 1 row",
add_fn = font_black,
as_note = FALSE)
}
@ -349,7 +429,7 @@ first_isolate <- function(x = NULL,
}
if (length(c(row.start:row.end)) == pm_n_distinct(x[c(row.start:row.end), col_mo, drop = TRUE])) {
if (info == TRUE) {
message_("=> Found ", font_bold(paste(length(c(row.start:row.end)), "isolates")),
message_("=> Found ", font_bold(paste(length(c(row.start:row.end)), "first isolates")),
", as all isolates were different microorganisms",
add_fn = font_black,
as_note = FALSE)
@ -378,18 +458,18 @@ first_isolate <- function(x = NULL,
}))
weighted.notice <- ""
if (!is.null(col_keyantibiotics)) {
if (!is.null(col_keyantimicrobials)) {
weighted.notice <- "weighted "
if (info == TRUE) {
if (type == "keyantibiotics") {
message_("[Criterion] Base inclusion on key antibiotics, ",
if (type == "keyantimicrobials") {
message_("Basing inclusion on key antimicrobials, ",
ifelse(ignore_I == FALSE, "not ", ""),
"ignoring I",
add_fn = font_black,
as_note = FALSE)
}
if (type == "points") {
message_("[Criterion] Base inclusion on key antibiotics, using points threshold of "
message_("Basing inclusion on all antimicrobial results, using a points threshold of "
, points_threshold,
add_fn = font_black,
as_note = FALSE)
@ -397,12 +477,12 @@ first_isolate <- function(x = NULL,
}
type_param <- type
x$other_key_ab <- !key_antibiotics_equal(y = x$newvar_key_ab,
z = pm_lag(x$newvar_key_ab),
type = type_param,
ignore_I = ignore_I,
points_threshold = points_threshold,
na.rm = TRUE)
x$other_key_ab <- !antimicrobials_equal(y = x$newvar_key_ab,
z = pm_lag(x$newvar_key_ab),
type = type_param,
ignore_I = ignore_I,
points_threshold = points_threshold,
na.rm = TRUE)
# with key antibiotics
x$newvar_first_isolate <- pm_if_else(x$newvar_row_index_sorted >= row.start &
x$newvar_row_index_sorted <= row.end &
@ -429,12 +509,12 @@ first_isolate <- function(x = NULL,
}
if (!is.null(col_icu)) {
if (icu_exclude == TRUE) {
message_("[Criterion] Exclude isolates from ICU.",
message_("Excluding isolates from ICU.",
add_fn = font_black,
as_note = FALSE)
x[which(as.logical(x[, col_icu, drop = TRUE])), "newvar_first_isolate"] <- FALSE
} else {
message_("[Criterion] Include isolates from ICU.",
message_("Including isolates from ICU.",
add_fn = font_black,
as_note = FALSE)
}
@ -459,7 +539,8 @@ first_isolate <- function(x = NULL,
paste0('"', x, '"')
}
})
cat("\nGroup: ", paste0(names(group), " = ", group, collapse = ", "), "\n", sep = "")
message_("\nGroup: ", paste0(names(group), " = ", group, collapse = ", "), "\n",
as_note = FALSE)
}
}
}
@ -508,11 +589,11 @@ first_isolate <- function(x = NULL,
if (p_found_total != p_found_scope) {
msg_txt <- paste0("=> Found ",
font_bold(paste0(n_found, " first ", weighted.notice, "isolates")),
" (", p_found_scope, " within scope and ", p_found_total, " of total where a microbial ID was available)")
" (", method, ", ", p_found_scope, " within scope and ", p_found_total, " of total where a microbial ID was available)")
} else {
msg_txt <- paste0("=> Found ",
font_bold(paste0(n_found, " first ", weighted.notice, "isolates")),
" (", p_found_total, " of total where a microbial ID was available)")
" (", method, ", ", p_found_total, " of total where a microbial ID was available)")
}
message_(msg_txt, add_fn = font_black, as_note = FALSE)
}
@ -527,6 +608,7 @@ filter_first_isolate <- function(x = NULL,
col_date = NULL,
col_patient_id = NULL,
col_mo = NULL,
method = "episode-based",
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
@ -537,11 +619,13 @@ filter_first_isolate <- function(x = NULL,
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))
meet_criteria(col_mo, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(method, allow_class = "character", has_length = 1, is_in = c("phenotype-based", "episode-based", "patient-based", "isolate-based"))
subset(x, first_isolate(x = x,
col_date = col_date,
col_patient_id = col_patient_id,
col_mo = col_mo,
method = method,
...))
}
@ -551,7 +635,7 @@ filter_first_weighted_isolate <- function(x = NULL,
col_date = NULL,
col_patient_id = NULL,
col_mo = NULL,
col_keyantibiotics = NULL,
method = "phenotype-based",
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
@ -562,22 +646,12 @@ filter_first_weighted_isolate <- function(x = NULL,
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))
meet_criteria(col_mo, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_keyantibiotics, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
y <- x
if (is.null(col_keyantibiotics)) {
# first try to look for it
col_keyantibiotics <- search_type_in_df(x = x, type = "keyantibiotics")
# still NULL? Then create it since we are calling filter_first_WEIGHTED_isolate()
if (is.null(col_keyantibiotics)) {
y$keyab <- suppressMessages(key_antibiotics(x,
col_mo = col_mo,
...))
col_keyantibiotics <- "keyab"
}
}
meet_criteria(method, allow_class = "character", has_length = 1, is_in = c("phenotype-based", "episode-based", "patient-based", "isolate-based"))
subset(x, first_isolate(x = y,
subset(x, first_isolate(x = x,
col_date = col_date,
col_patient_id = col_patient_id))
col_patient_id = col_patient_id,
col_mo = col_mo,
method = method,
...))
}

View File

@ -102,6 +102,7 @@ get_column_abx <- function(x,
verbose = FALSE,
info = TRUE,
only_rsi_columns = FALSE,
sort = TRUE,
...) {
meet_criteria(x, allow_class = "data.frame")
meet_criteria(soft_dependencies, allow_class = "character", allow_NULL = TRUE)
@ -109,6 +110,7 @@ get_column_abx <- function(x,
meet_criteria(verbose, allow_class = "logical", has_length = 1)
meet_criteria(info, allow_class = "logical", has_length = 1)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
meet_criteria(sort, allow_class = "logical", has_length = 1)
if (info == TRUE) {
message_("Auto-guessing columns suitable for analysis", appendLF = FALSE, as_note = FALSE)
@ -186,11 +188,15 @@ get_column_abx <- function(x,
}
# sort on name
x <- x[order(names(x), x)]
if (sort == TRUE) {
x <- x[order(names(x), x)]
}
duplicates <- c(x[duplicated(x)], x[duplicated(names(x))])
duplicates <- duplicates[unique(names(duplicates))]
x <- c(x[!names(x) %in% names(duplicates)], duplicates)
x <- x[order(names(x), x)]
if (sort == TRUE) {
x <- x[order(names(x), x)]
}
# succeeded with auto-guessing
if (info == TRUE) {

View File

@ -1,360 +0,0 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
# GNU General Public License version 2.0 (GNU GPL-2), as published by #
# the Free Software Foundation. #
# We created this package for both routine data analysis and academic #
# research and it was publicly released in the hope that it will be #
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' 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 can then be called first 'weighted' isolates.
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a [data.frame] with antibiotics columns, like `AMX` or `amox`. Can be left blank to determine automatically
#' @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()]).
#' @param GramPos_1,GramPos_2,GramPos_3,GramPos_4,GramPos_5,GramPos_6 column names of antibiotics for **Gram-positives**, case-insensitive. See details for which antibiotics will be used at default (which are guessed with [guess_ab_col()]).
#' @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 arguments passed on to functions
#' @details
#' The [key_antibiotics()] function is context-aware. This means that then the `x` argument can be left blank, 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.
#'
#' At default, the antibiotics that are used for **Gram-positive bacteria** are:
#' - Amoxicillin
#' - Amoxicillin/clavulanic acid
#' - Cefuroxime
#' - Piperacillin/tazobactam
#' - Ciprofloxacin
#' - Trimethoprim/sulfamethoxazole
#' - Vancomycin
#' - Teicoplanin
#' - Tetracycline
#' - Erythromycin
#' - Oxacillin
#' - Rifampin
#'
#' At default the antibiotics that are used for **Gram-negative bacteria** are:
#' - Amoxicillin
#' - Amoxicillin/clavulanic acid
#' - Cefuroxime
#' - Piperacillin/tazobactam
#' - Ciprofloxacin
#' - Trimethoprim/sulfamethoxazole
#' - Gentamicin
#' - Tobramycin
#' - Colistin
#' - Cefotaxime
#' - Ceftazidime
#' - Meropenem
#'
#' The function [key_antibiotics_equal()] checks the characters returned by [key_antibiotics()] for equality, and returns a [`logical`] vector.
#' @inheritSection first_isolate Key Antibiotics
#' @rdname key_antibiotics
#' @export
#' @seealso [first_isolate()]
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # `example_isolates` is a data set available in the AMR package.
#' # See ?example_isolates.
#'
#' # output of the `key_antibiotics()` function could be like this:
#' strainA <- "SSSRR.S.R..S"
#' strainB <- "SSSIRSSSRSSS"
#'
#' # 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 character differs
#'
#' \donttest{
#' if (require("dplyr")) {
#' # set key antibiotics to a new variable
#' my_patients <- example_isolates %>%
#' mutate(keyab = key_antibiotics()) %>% # no need to define `x`
#' mutate(
#' # now calculate first isolates
#' first_regular = first_isolate(col_keyantibiotics = FALSE),
#' # and first WEIGHTED isolates
#' first_weighted = first_isolate(col_keyantibiotics = "keyab")
#' )
#'
#' # 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)
#' }
#' }
key_antibiotics <- function(x = NULL,
col_mo = NULL,
universal_1 = guess_ab_col(x, "amoxicillin"),
universal_2 = guess_ab_col(x, "amoxicillin/clavulanic acid"),
universal_3 = guess_ab_col(x, "cefuroxime"),
universal_4 = guess_ab_col(x, "piperacillin/tazobactam"),
universal_5 = guess_ab_col(x, "ciprofloxacin"),
universal_6 = guess_ab_col(x, "trimethoprim/sulfamethoxazole"),
GramPos_1 = guess_ab_col(x, "vancomycin"),
GramPos_2 = guess_ab_col(x, "teicoplanin"),
GramPos_3 = guess_ab_col(x, "tetracycline"),
GramPos_4 = guess_ab_col(x, "erythromycin"),
GramPos_5 = guess_ab_col(x, "oxacillin"),
GramPos_6 = guess_ab_col(x, "rifampin"),
GramNeg_1 = guess_ab_col(x, "gentamicin"),
GramNeg_2 = guess_ab_col(x, "tobramycin"),
GramNeg_3 = guess_ab_col(x, "colistin"),
GramNeg_4 = guess_ab_col(x, "cefotaxime"),
GramNeg_5 = guess_ab_col(x, "ceftazidime"),
GramNeg_6 = guess_ab_col(x, "meropenem"),
warnings = TRUE,
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
x <- tryCatch(get_current_data(arg_name = "x", call = -2), error = function(e) x)
}
meet_criteria(x, allow_class = "data.frame") # also checks dimensions to be >0
meet_criteria(col_mo, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE, is_in = colnames(x))
meet_criteria(universal_1, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_2, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_3, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_4, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_5, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_6, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_1, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_2, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_3, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_4, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_5, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_6, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_1, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_2, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_3, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_4, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_5, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_6, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(warnings, allow_class = "logical", has_length = 1)
# force regular data.frame, not a tibble or data.table
x <- as.data.frame(x, stringsAsFactors = FALSE)
dots <- unlist(list(...))
if (length(dots) != 0) {
# backwards compatibility with old arguments
dots.names <- names(dots)
if ("info" %in% dots.names) {
warnings <- dots[which(dots.names == "info")]
}
}
# try to find columns based on type
# -- mo
if (is.null(col_mo)) {
col_mo <- search_type_in_df(x = x, type = "mo")
}
if (is.null(col_mo)) {
warning_("No column found for `col_mo`, ignoring antimicrobial agents set for Gram-negative and Gram-positive bacteria", call = FALSE)
x$gramstain <- NA_character_
} else {
x$gramstain <- mo_gramstain(as.mo(x[, col_mo, drop = TRUE]), language = NULL)
}
x$key_ab <- NA_character_
# check columns
col.list <- c(universal_1, universal_2, universal_3, universal_4, universal_5, universal_6,
GramPos_1, GramPos_2, GramPos_3, GramPos_4, GramPos_5, GramPos_6,
GramNeg_1, GramNeg_2, GramNeg_3, GramNeg_4, GramNeg_5, GramNeg_6)
check_available_columns <- function(x, col.list, warnings = TRUE) {
# check columns
col.list <- col.list[!is.na(col.list) & !is.null(col.list)]
names(col.list) <- col.list
col.list.bak <- col.list
# are they available as upper case or lower case then?
for (i in seq_len(length(col.list))) {
if (is.null(col.list[i]) | isTRUE(is.na(col.list[i]))) {
col.list[i] <- NA
} else if (toupper(col.list[i]) %in% colnames(x)) {
col.list[i] <- toupper(col.list[i])
} else if (tolower(col.list[i]) %in% colnames(x)) {
col.list[i] <- tolower(col.list[i])
} else if (!col.list[i] %in% colnames(x)) {
col.list[i] <- NA
}
}
if (!all(col.list %in% colnames(x))) {
if (warnings == TRUE) {
warning_("Some columns do not exist and will be ignored: ",
col.list.bak[!(col.list %in% colnames(x))] %pm>% toString(),
".\nTHIS MAY STRONGLY INFLUENCE THE OUTCOME.",
immediate = TRUE,
call = FALSE)
}
}
col.list
}
col.list <- check_available_columns(x = x, col.list = col.list, warnings = warnings)
universal_1 <- col.list[universal_1]
universal_2 <- col.list[universal_2]
universal_3 <- col.list[universal_3]
universal_4 <- col.list[universal_4]
universal_5 <- col.list[universal_5]
universal_6 <- col.list[universal_6]
GramPos_1 <- col.list[GramPos_1]
GramPos_2 <- col.list[GramPos_2]
GramPos_3 <- col.list[GramPos_3]
GramPos_4 <- col.list[GramPos_4]
GramPos_5 <- col.list[GramPos_5]
GramPos_6 <- col.list[GramPos_6]
GramNeg_1 <- col.list[GramNeg_1]
GramNeg_2 <- col.list[GramNeg_2]
GramNeg_3 <- col.list[GramNeg_3]
GramNeg_4 <- col.list[GramNeg_4]
GramNeg_5 <- col.list[GramNeg_5]
GramNeg_6 <- col.list[GramNeg_6]
universal <- c(universal_1, universal_2, universal_3,
universal_4, universal_5, universal_6)
gram_positive <- c(universal,
GramPos_1, GramPos_2, GramPos_3,
GramPos_4, GramPos_5, GramPos_6)
gram_positive <- gram_positive[!is.null(gram_positive)]
gram_positive <- gram_positive[!is.na(gram_positive)]
if (length(gram_positive) < 12 & !all(is.na(x$gramstain)) & message_not_thrown_before("key_antibiotics.grampos")) {
warning_("Only using ", length(gram_positive), " different antibiotics as key antibiotics for Gram-positives. See ?key_antibiotics.", call = FALSE)
remember_thrown_message("key_antibiotics.grampos")
}
gram_negative <- c(universal,
GramNeg_1, GramNeg_2, GramNeg_3,
GramNeg_4, GramNeg_5, GramNeg_6)
gram_negative <- gram_negative[!is.null(gram_negative)]
gram_negative <- gram_negative[!is.na(gram_negative)]
if (length(gram_negative) < 12 & !all(is.na(x$gramstain)) & message_not_thrown_before("key_antibiotics.gramneg")) {
warning_("Only using ", length(gram_negative), " different antibiotics as key antibiotics for Gram-negatives. See ?key_antibiotics.", call = FALSE)
remember_thrown_message("key_antibiotics.gramneg")
}
# Gram +
x$key_ab <- pm_if_else(x$gramstain == "Gram-positive",
tryCatch(apply(X = x[, gram_positive],
MARGIN = 1,
FUN = function(x) paste(x, collapse = "")),
error = function(e) paste0(rep(".", 12), collapse = "")),
as.character(x$key_ab))
# Gram -
x$key_ab <- pm_if_else(x$gramstain == "Gram-negative",
tryCatch(apply(X = x[, gram_negative],
MARGIN = 1,
FUN = function(x) paste(x, collapse = "")),
error = function(e) paste0(rep(".", 12), collapse = "")),
as.character(x$key_ab))
# format
key_abs <- toupper(gsub("(NA|NULL|[^RSIrsi])", ".", x$key_ab))
if (pm_n_distinct(key_abs) == 1) {
warning_("No distinct key antibiotics determined.", call = FALSE)
}
key_abs
}
#' @rdname key_antibiotics
#' @param info unused - previously used to indicate whether a progress bar should print
#' @param na.rm a [logical] to indicate whether comparison with `NA` should return `FALSE` (defaults to `TRUE` for backwards compatibility)
#' @export
key_antibiotics_equal <- function(y,
z,
type = c("keyantibiotics", "points"),
ignore_I = TRUE,
points_threshold = 2,
info = FALSE,
na.rm = TRUE,
...) {
meet_criteria(y, allow_class = "character")
meet_criteria(z, allow_class = "character")
if (length(type) == 2) {
type <- type[1L]
}
meet_criteria(type, allow_class = "character", has_length = 1, is_in = c("keyantibiotics", "points"))
meet_criteria(ignore_I, allow_class = "logical", has_length = 1)
meet_criteria(points_threshold, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(info, allow_class = "logical", has_length = 1)
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
stop_ifnot(length(y) == length(z), "length of `y` and `z` must be equal")
key2rsi <- function(val) {
as.double(as.rsi(gsub(".", NA_character_, unlist(strsplit(val, "")), fixed = TRUE)))
}
y <- lapply(y, key2rsi)
z <- lapply(z, key2rsi)
determine_equality <- function(a, b, type, points_threshold, ignore_I) {
if (length(a) != length(b)) {
# incomparable, so not equal
return(FALSE)
}
# ignore NAs on both sides
NA_ind <- which(is.na(a) | is.na(b))
a[NA_ind] <- NA_real_
b[NA_ind] <- NA_real_
if (type == "points") {
# count points for every single character:
# - no change is 0 points
# - I <-> S|R is 0.5 point
# - S|R <-> R|S is 1 point
# use the levels of as.rsi (S = 1, I = 2, R = 3)
(sum(abs(a - b), na.rm = TRUE) / 2) < points_threshold
} else {
if (ignore_I == TRUE) {
ind <- which(a == 2 | b == 2) # since as.double(as.rsi("I")) == 2
a[ind] <- NA_real_
b[ind] <- NA_real_
}
all(a == b, na.rm = TRUE)
}
}
out <- unlist(mapply(FUN = determine_equality,
y,
z,
MoreArgs = list(type = type,
points_threshold = points_threshold,
ignore_I = ignore_I),
SIMPLIFY = FALSE,
USE.NAMES = FALSE))
if (na.rm == FALSE) {
out[is.na(y) | is.na(z)] <- NA
} else {
# NA means not equal if `na.rm == TRUE`, as per the manual
out[is.na(y) | is.na(z)] <- FALSE
}
out
}

327
R/key_antimicrobials.R Executable file
View File

@ -0,0 +1,327 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
# GNU General Public License version 2.0 (GNU GPL-2), as published by #
# the Free Software Foundation. #
# We created this package for both routine data analysis and academic #
# research and it was publicly released in the hope that it will be #
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' (Key) Antimicrobials for First Weighted Isolates
#'
#' These functions can be used to determine first weighted isolates by considering the phenotype for isolate selection (see [first_isolate()]). Using a phenotype-based method to determine first isolates is more reliable than methods that disregard phenotypes.
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a [data.frame] with antibiotics columns, like `AMX` or `amox`. Can be left blank to determine automatically
#' @param y,z character vectors to compare
#' @inheritParams first_isolate
#' @param universal names of **broad-spectrum** antimicrobial agents, case-insensitive. Set to `NULL` to ignore. See *Details* for the default agents.
#' @param gram_negative names of antibiotic agents for **Gram-positives**, case-insensitive. Set to `NULL` to ignore. See *Details* for the default agents.
#' @param gram_positive names of antibiotic agents for **Gram-negatives**, case-insensitive. Set to `NULL` to ignore. See *Details* for the default agents.
#' @param antifungal names of antifungal agents for **fungi**, case-insensitive. Set to `NULL` to ignore. See *Details* for the default agents.
#' @param ... ignored, allows for future extensions
#' @details
#' The [key_antimicrobials()] and [all_antimicrobials()] functions are context-aware. This means that then the `x` argument can be left blank, see *Examples*.
#'
#' The function [key_antimicrobials()] returns a character vector with 12 antimicrobial results for every isolate. The function [all_antimicrobials()] returns a character vector with all antimicrobial results for every isolate. These vectors can then be compared using [antimicrobials_equal()], to check if two isolates have generally the same antibiogram. Missing and invalid values are replaced with a dot (`"."`) by [key_antimicrobials()] and ignored by [antimicrobials_equal()].
#'
#' Please see the [first_isolate()] function how these important functions enable the 'phenotype-based' method for determination of first isolates.
#'
#' The default antimicrobial agents used for **all rows** (set in `universal`) are:
#'
#' - Ampicillin
#' - Amoxicillin/clavulanic acid
#' - Cefuroxime
#' - Ciprofloxacin
#' - Piperacillin/tazobactam
#' - Trimethoprim/sulfamethoxazole
#'
#' The default antimicrobial agents used for **Gram-negative bacteria** (set in `gram_negative`) are:
#'
#' - Cefotaxime
#' - Ceftazidime
#' - Colistin
#' - Gentamicin
#' - Meropenem
#' - Tobramycin
#'
#' The default antimicrobial agents used for **Gram-positive bacteria** (set in `gram_positive`) are:
#'
#' - Erythromycin
#' - Oxacillin
#' - Rifampin
#' - Teicoplanin
#' - Tetracycline
#' - Vancomycin
#'
#'
#' The default antimicrobial agents used for **fungi** (set in `antifungal`) are:
#'
#' - Anidulafungin
#' - Caspofungin
#' - Fluconazole
#' - Miconazole
#' - Nystatin
#' - Voriconazole
#' @rdname key_antimicrobials
#' @export
#' @seealso [first_isolate()]
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # `example_isolates` is a data set available in the AMR package.
#' # See ?example_isolates.
#'
#' # output of the `key_antimicrobials()` function could be like this:
#' strainA <- "SSSRR.S.R..S"
#' strainB <- "SSSIRSSSRSSS"
#'
#' # those strings can be compared with:
#' antimicrobials_equal(strainA, strainB, type = "keyantimicrobials")
#' # TRUE, because I is ignored (as well as missing values)
#'
#' antimicrobials_equal(strainA, strainB, type = "keyantimicrobials", ignore_I = FALSE)
#' # 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_antimicrobials(antifungal = NULL)) %>% # no need to define `x`
#' mutate(
#' # now calculate first isolates
#' first_regular = first_isolate(col_keyantimicrobials = FALSE),
#' # and first WEIGHTED isolates
#' first_weighted = first_isolate(col_keyantimicrobials = "keyab")
#' )
#'
#' # Check the difference, in this data set it results in more isolates:
#' sum(my_patients$first_regular, na.rm = TRUE)
#' sum(my_patients$first_weighted, na.rm = TRUE)
#' }
#' }
key_antimicrobials <- function(x = NULL,
col_mo = NULL,
universal = c("ampicillin", "amoxicillin/clavulanic acid", "cefuroxime",
"piperacillin/tazobactam", "ciprofloxacin", "trimethoprim/sulfamethoxazole"),
gram_negative = c("gentamicin", "tobramycin", "colistin",
"cefotaxime", "ceftazidime", "meropenem"),
gram_positive = c("vancomycin", "teicoplanin", "tetracycline",
"erythromycin", "oxacillin", "rifampin"),
antifungal = c("anidulafungin", "caspofungin", "fluconazole",
"miconazole", "nystatin", "voriconazole"),
only_rsi_columns = FALSE,
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
x <- tryCatch(get_current_data(arg_name = "x", call = -2), error = function(e) x)
}
meet_criteria(x, allow_class = "data.frame") # also checks dimensions to be >0
meet_criteria(col_mo, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE, is_in = colnames(x))
meet_criteria(universal, allow_class = "character", allow_NULL = TRUE)
meet_criteria(gram_negative, allow_class = "character", allow_NULL = TRUE)
meet_criteria(gram_positive, allow_class = "character", allow_NULL = TRUE)
meet_criteria(antifungal, allow_class = "character", allow_NULL = TRUE)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
# force regular data.frame, not a tibble or data.table
x <- as.data.frame(x, stringsAsFactors = FALSE)
cols <- get_column_abx(x, info = FALSE, only_rsi_columns = only_rsi_columns)
# try to find columns based on type
# -- mo
if (is.null(col_mo)) {
col_mo <- search_type_in_df(x = x, type = "mo", info = FALSE)
}
if (is.null(col_mo)) {
warning_("No column found for `col_mo`, ignoring antibiotics set in `gram_negative` and `gram_positive`, and antimycotics set in `antifungal`", call = FALSE)
gramstain <- NA_character_
kingdom <- NA_character_
} else {
x.mo <- as.mo(x[, col_mo, drop = TRUE])
gramstain <- mo_gramstain(x.mo, language = NULL)
kingdom <- mo_kingdom(x.mo, language = NULL)
}
AMR_string <- function(x, values, name, filter, cols = cols) {
if (is.null(values)) {
return(rep(NA_character_, length(which(filter))))
}
values_old_length <- length(values)
values <- as.ab(values, flag_multiple_results = FALSE, info = FALSE)
values <- cols[names(cols) %in% values]
values_new_length <- length(values)
if (values_new_length < values_old_length &
any(filter, na.rm = TRUE) &
message_not_thrown_before(paste0("key_antimicrobials.", name))) {
warning_(ifelse(values_new_length == 0,
"No columns available ",
paste0("Only using ", values_new_length, " out of ", values_old_length, " defined columns ")),
"as key antimicrobials for ", name, "s. See ?key_antimicrobials.",
call = FALSE)
remember_thrown_message(paste0("key_antimicrobials.", name))
}
generate_antimcrobials_string(x[which(filter), c(universal, values), drop = FALSE])
}
if (is.null(universal)) {
universal <- character(0)
} else {
universal <- as.ab(universal, flag_multiple_results = FALSE, info = FALSE)
universal <- cols[names(cols) %in% universal]
}
key_ab <- rep(NA_character_, nrow(x))
key_ab[which(gramstain == "Gram-negative")] <- AMR_string(x = x,
values = gram_negative,
name = "Gram-negative",
filter = gramstain == "Gram-negative",
cols = cols)
key_ab[which(gramstain == "Gram-positive")] <- AMR_string(x = x,
values = gram_positive,
name = "Gram-positive",
filter = gramstain == "Gram-positive",
cols = cols)
key_ab[which(kingdom == "Fungi")] <- AMR_string(x = x,
values = antifungal,
name = "antifungal",
filter = kingdom == "Fungi",
cols = cols)
# back-up - only use `universal`
key_ab[which(is.na(key_ab))] <- AMR_string(x = x,
values = character(0),
name = "",
filter = is.na(key_ab),
cols = cols)
if (length(unique(key_ab)) == 1) {
warning_("No distinct key antibiotics determined.", call = FALSE)
}
key_ab
}
#' @rdname key_antimicrobials
#' @export
all_antimicrobials <- function(x = NULL,
only_rsi_columns = FALSE,
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
x <- tryCatch(get_current_data(arg_name = "x", call = -2), error = function(e) x)
}
meet_criteria(x, allow_class = "data.frame") # also checks dimensions to be >0
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
# force regular data.frame, not a tibble or data.table
x <- as.data.frame(x, stringsAsFactors = FALSE)
cols <- get_column_abx(x, only_rsi_columns = only_rsi_columns, info = FALSE, sort = FALSE)
generate_antimcrobials_string(x[ , cols, drop = FALSE])
}
generate_antimcrobials_string <- function(df) {
if (NCOL(df) == 0) {
return(rep("", NROW(df)))
}
if (NROW(df) == 0) {
return(character(0))
}
out <- tryCatch(
do.call(paste0,
lapply(as.list(df),
function(x) {
x <- toupper(as.character(x))
x[!x %in% c("R", "S", "I")] <- "."
paste(x)
})),
error = function(e) rep(strrep(".", NCOL(df)), NROW(df)))
out
}
#' @rdname key_antimicrobials
#' @param info unused - previously used to indicate whether a progress bar should print
#' @export
antimicrobials_equal <- function(y,
z,
type = c("points", "keyantimicrobials"),
ignore_I = TRUE,
points_threshold = 2,
info = FALSE,
...) {
meet_criteria(y, allow_class = "character")
meet_criteria(z, allow_class = "character")
stop_if(missing(type), "argument \"type\" is missing, with no default")
meet_criteria(type, allow_class = "character", has_length = 1, is_in = c("points", "keyantimicrobials"))
meet_criteria(ignore_I, allow_class = "logical", has_length = 1)
meet_criteria(points_threshold, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(info, allow_class = "logical", has_length = 1)
stop_ifnot(length(y) == length(z), "length of `y` and `z` must be equal")
key2rsi <- function(val) {
as.double(as.rsi(gsub(".", NA_character_, unlist(strsplit(val, "")), fixed = TRUE)))
}
y <- lapply(y, key2rsi)
z <- lapply(z, key2rsi)
determine_equality <- function(a, b, type, points_threshold, ignore_I) {
if (length(a) != length(b)) {
# incomparable, so not equal
return(FALSE)
}
# ignore NAs on both sides
NA_ind <- which(is.na(a) | is.na(b))
a[NA_ind] <- NA_real_
b[NA_ind] <- NA_real_
if (type == "points") {
# count points for every single character:
# - no change is 0 points
# - I <-> S|R is 0.5 point
# - S|R <-> R|S is 1 point
# use the levels of as.rsi (S = 1, I = 2, R = 3)
# and divide by 2 (S = 0.5, I = 1, R = 1.5)
(sum(abs(a - b), na.rm = TRUE) / 2) < points_threshold
} else {
if (ignore_I == TRUE) {
ind <- which(a == 2 | b == 2) # since as.double(as.rsi("I")) == 2
a[ind] <- NA_real_
b[ind] <- NA_real_
}
all(a == b, na.rm = TRUE)
}
}
out <- unlist(mapply(FUN = determine_equality,
y,
z,
MoreArgs = list(type = type,
points_threshold = points_threshold,
ignore_I = ignore_I),
SIMPLIFY = FALSE,
USE.NAMES = FALSE))
out[is.na(y) | is.na(z)] <- NA
out
}

View File

@ -1027,10 +1027,8 @@ summary.rsi <- function(object, ...) {
#' @method c rsi
#' @export
#' @noRd
c.rsi <- function(x, ...) {
y <- unlist(lapply(list(...), as.character))
x <- as.character(x)
as.rsi(c(x, y))
c.rsi <- function(...) {
as.rsi(unlist(lapply(list(...), as.character)))
}
#' @method unique rsi

View File

@ -155,7 +155,7 @@ reference:
- "`count`"
- "`is_new_episode`"
- "`first_isolate`"
- "`key_antibiotics`"
- "`key_antimicrobials`"
- "`mdro`"
- "`count`"
- "`plot`"

Binary file not shown.

View File

@ -81,7 +81,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="https://msberends.github.io/AMR//index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -81,7 +81,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -81,7 +81,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -81,7 +81,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -42,7 +42,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -81,7 +81,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>
@ -236,13 +236,13 @@
<small>Source: <a href='https://github.com/msberends/AMR/blob/master/NEWS.md'><code>NEWS.md</code></a></small>
</div>
<div id="amr-1609009" class="section level1">
<h1 class="page-header" data-toc-text="1.6.0.9009">
<a href="#amr-1609009" class="anchor"></a>AMR 1.6.0.9009<small> Unreleased </small>
<div id="amr-1609010" class="section level1">
<h1 class="page-header" data-toc-text="1.6.0.9010">
<a href="#amr-1609010" class="anchor"></a>AMR 1.6.0.9010<small> Unreleased </small>
</h1>
<div id="last-updated-23-april-2021" class="section level2">
<div id="last-updated-26-april-2021" class="section level2">
<h2 class="hasAnchor">
<a href="#last-updated-23-april-2021" class="anchor"></a><small>Last updated: 23 April 2021</small>
<a href="#last-updated-26-april-2021" class="anchor"></a><small>Last updated: 26 April 2021</small>
</h2>
<div id="new" class="section level3">
<h3 class="hasAnchor">
@ -250,6 +250,20 @@
<ul>
<li>Function <code><a href="../reference/custom_eucast_rules.html">custom_eucast_rules()</a></code> that brings support for custom AMR rules in <code><a href="../reference/eucast_rules.html">eucast_rules()</a></code>
</li>
<li>Support for all four methods to determine first isolates as summarised by Hindler <em>et al</em> (doi: <a href="https://doi.org/10.1086/511864">10.1086/511864</a>): isolate-based, patient-based, episode-based and phenotype-based. The last method is now the default.
<ul>
<li>Since fungal isolates can also be selected, new functions <code><a href="../reference/key_antimicrobials.html">key_antimicrobials()</a></code> and <code><a href="../reference/key_antimicrobials.html">all_antimicrobials()</a></code> have replaced the now deprecated function <code><a href="../reference/AMR-deprecated.html">key_antibiotics()</a></code>
</li>
<li>Using <code><a href="../reference/key_antimicrobials.html">key_antimicrobials()</a></code> still only selects six preferred antibiotics for Gram-negatives, six for Gram-positives, and six universal antibiotics. It has a new <code>antifungal</code> argument to set antifungal agents (antimycotics).</li>
<li>The <code><a href="../reference/first_isolate.html">first_isolate()</a></code> function gained the argument <code>method</code> that has to be “phenotype-based”, “episode-based”, “patient-based”, or “isolate-based”. The old behaviour is equal to “episode-based”, while the new default is “phenotype-based”.</li>
<li>Using <code>type == "points"</code> in the <code><a href="../reference/first_isolate.html">first_isolate()</a></code> function for phenotype-based selection will now consider all antimicrobial drugs in the data set, using the new <code><a href="../reference/key_antimicrobials.html">all_antimicrobials()</a></code>
</li>
<li>The <code><a href="../reference/first_isolate.html">first_isolate()</a></code> function can now take a vector of values for <code>col_keyantibiotics</code> and can have an episode length of <code>Inf</code>
</li>
<li>The <code><a href="../reference/first_isolate.html">filter_first_isolate()</a></code> function has not changed, as it uses the episode-based method. The <code><a href="../reference/first_isolate.html">filter_first_weighted_isolate()</a></code> may now include more isolates as uses the phenotype-based method.</li>
<li>The documentation of the <code><a href="../reference/first_isolate.html">first_isolate()</a></code> and <code><a href="../reference/key_antimicrobials.html">key_antimicrobials()</a></code> functions has been completely rewritten.</li>
</ul>
</li>
</ul>
</div>
<div id="changed" class="section level3">
@ -267,9 +281,6 @@
<li>The <code>example_isolates</code> data set now contains some (fictitious) zero-year old patients</li>
<li>Fix for minor translation errors</li>
<li>Printing of microbial codes in a <code>data.frame</code> or <code>tibble</code> now gives a warning if the data contains old microbial codes (from a previous AMR package version)</li>
<li>
<code><a href="../reference/first_isolate.html">first_isolate()</a></code> can now take a vector of values for <code>col_keyantibiotics</code> and can have an episode length of <code>Inf</code>
</li>
<li>Extended the <code><a href="../reference/like.html">like()</a></code> functions:
<ul>
<li><p>Now checks if <code>pattern</code> is a <em>valid</em> regular expression</p></li>
@ -287,13 +298,6 @@
<li>Fixed an installation error on R-3.0</li>
<li>Added <code>info</code> argument to <code><a href="../reference/as.mo.html">as.mo()</a></code> to turn on/off the progress bar</li>
<li>Fixed a bug that <code>col_mo</code> for some functions (esp. <code><a href="../reference/eucast_rules.html">eucast_rules()</a></code> and <code><a href="../reference/mdro.html">mdro()</a></code>) could not be column names of the <code>microorganisms</code> data set as it would throw an error</li>
<li>Using <code><a href="../reference/first_isolate.html">first_isolate()</a></code> with key antibiotics:
<ul>
<li>Fixed a bug in the algorithm when using <code>type == "points"</code>, that now leads to inclusion of slightly more isolates</li>
<li>Big speed improvement for <code><a href="../reference/key_antibiotics.html">key_antibiotics_equal()</a></code> when using <code>type == "points"</code>
</li>
</ul>
</li>
</ul>
</div>
</div>
@ -487,7 +491,7 @@
<li>
<code><a href="../reference/first_isolate.html">first_isolate()</a></code>,</li>
<li>
<code><a href="../reference/key_antibiotics.html">key_antibiotics()</a></code>,</li>
<code><a href="../reference/AMR-deprecated.html">key_antibiotics()</a></code>,</li>
<li>
<code><a href="../reference/mdro.html">mdro()</a></code>,</li>
<li>
@ -1205,7 +1209,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
<li>Renamed function <code>p.symbol()</code> to <code><a href="../reference/AMR-deprecated.html">p_symbol()</a></code> (the former is now deprecated and will be removed in a future version)</li>
<li>Using negative values for <code>x</code> in <code><a href="../reference/age_groups.html">age_groups()</a></code> will now introduce <code>NA</code>s and not return an error anymore</li>
<li>Fix for determining the systems language</li>
<li>Fix for <code><a href="../reference/key_antibiotics.html">key_antibiotics()</a></code> on foreign systems</li>
<li>Fix for <code><a href="../reference/AMR-deprecated.html">key_antibiotics()</a></code> on foreign systems</li>
<li>Added 80 new LIS codes for microorganisms</li>
<li>Relabeled the factor levels of <code><a href="../reference/mdro.html">mdr_tb()</a></code>
</li>
@ -1654,7 +1658,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
</ul>
</li>
<li>Function <code><a href="../reference/ggplot_rsi.html">scale_y_percent()</a></code> now contains the <code>limits</code> argument</li>
<li>Automatic argument filling for <code><a href="../reference/mdro.html">mdro()</a></code>, <code><a href="../reference/key_antibiotics.html">key_antibiotics()</a></code> and <code><a href="../reference/eucast_rules.html">eucast_rules()</a></code>
<li>Automatic argument filling for <code><a href="../reference/mdro.html">mdro()</a></code>, <code><a href="../reference/AMR-deprecated.html">key_antibiotics()</a></code> and <code><a href="../reference/eucast_rules.html">eucast_rules()</a></code>
</li>
<li>Updated examples for resistance prediction (<code><a href="../reference/resistance_predict.html">resistance_predict()</a></code> function)</li>
<li>Fix for <code><a href="../reference/as.mic.html">as.mic()</a></code> to support more values ending in (several) zeroes</li>

View File

@ -12,7 +12,7 @@ articles:
datasets: datasets.html
resistance_predict: resistance_predict.html
welcome_to_AMR: welcome_to_AMR.html
last_built: 2021-04-23T14:13Z
last_built: 2021-04-26T21:56Z
urls:
reference: https://msberends.github.io/AMR//reference
article: https://msberends.github.io/AMR//articles

View File

@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.5.0.9016</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>
@ -242,7 +242,43 @@
<p>These functions are so-called '<a href='https://rdrr.io/r/base/Deprecated.html'>Deprecated</a>'. They will be removed in a future release. Using the functions will give a warning with the name of the function it has been replaced by (if there is one).</p>
</div>
<pre class="usage"><span class='fu'>p_symbol</span><span class='op'>(</span><span class='va'>p</span>, emptychar <span class='op'>=</span> <span class='st'>" "</span><span class='op'>)</span></pre>
<pre class="usage"><span class='fu'>p_symbol</span><span class='op'>(</span><span class='va'>p</span>, emptychar <span class='op'>=</span> <span class='st'>" "</span><span class='op'>)</span>
<span class='fu'>key_antibiotics</span><span class='op'>(</span>
x <span class='op'>=</span> <span class='cn'>NULL</span>,
col_mo <span class='op'>=</span> <span class='cn'>NULL</span>,
universal_1 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"amoxicillin"</span><span class='op'>)</span>,
universal_2 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"amoxicillin/clavulanic acid"</span><span class='op'>)</span>,
universal_3 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"cefuroxime"</span><span class='op'>)</span>,
universal_4 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"piperacillin/tazobactam"</span><span class='op'>)</span>,
universal_5 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"ciprofloxacin"</span><span class='op'>)</span>,
universal_6 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"trimethoprim/sulfamethoxazole"</span><span class='op'>)</span>,
GramPos_1 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"vancomycin"</span><span class='op'>)</span>,
GramPos_2 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"teicoplanin"</span><span class='op'>)</span>,
GramPos_3 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"tetracycline"</span><span class='op'>)</span>,
GramPos_4 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"erythromycin"</span><span class='op'>)</span>,
GramPos_5 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"oxacillin"</span><span class='op'>)</span>,
GramPos_6 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"rifampin"</span><span class='op'>)</span>,
GramNeg_1 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"gentamicin"</span><span class='op'>)</span>,
GramNeg_2 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"tobramycin"</span><span class='op'>)</span>,
GramNeg_3 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"colistin"</span><span class='op'>)</span>,
GramNeg_4 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"cefotaxime"</span><span class='op'>)</span>,
GramNeg_5 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"ceftazidime"</span><span class='op'>)</span>,
GramNeg_6 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"meropenem"</span><span class='op'>)</span>,
warnings <span class='op'>=</span> <span class='cn'>TRUE</span>,
<span class='va'>...</span>
<span class='op'>)</span>
<span class='fu'>key_antibiotics_equal</span><span class='op'>(</span>
<span class='va'>y</span>,
<span class='va'>z</span>,
type <span class='op'>=</span> <span class='st'>"keyantimicrobials"</span>,
ignore_I <span class='op'>=</span> <span class='cn'>TRUE</span>,
points_threshold <span class='op'>=</span> <span class='fl'>2</span>,
info <span class='op'>=</span> <span class='cn'>FALSE</span>,
na.rm <span class='op'>=</span> <span class='cn'>TRUE</span>,
<span class='va'>...</span>
<span class='op'>)</span></pre>
<h2 class="hasAnchor" id="retired-lifecycle"><a class="anchor" href="#retired-lifecycle"></a>Retired Lifecycle</h2>

View File

@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9007</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9007</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9007</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9007</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>
@ -250,12 +250,13 @@
col_testcode <span class='op'>=</span> <span class='cn'>NULL</span>,
col_specimen <span class='op'>=</span> <span class='cn'>NULL</span>,
col_icu <span class='op'>=</span> <span class='cn'>NULL</span>,
col_keyantibiotics <span class='op'>=</span> <span class='cn'>NULL</span>,
col_keyantimicrobials <span class='op'>=</span> <span class='cn'>NULL</span>,
episode_days <span class='op'>=</span> <span class='fl'>365</span>,
testcodes_exclude <span class='op'>=</span> <span class='cn'>NULL</span>,
icu_exclude <span class='op'>=</span> <span class='cn'>FALSE</span>,
specimen_group <span class='op'>=</span> <span class='cn'>NULL</span>,
type <span class='op'>=</span> <span class='st'>"keyantibiotics"</span>,
type <span class='op'>=</span> <span class='st'>"points"</span>,
method <span class='op'>=</span> <span class='fu'><a href='https://rdrr.io/r/base/c.html'>c</a></span><span class='op'>(</span><span class='st'>"phenotype-based"</span>, <span class='st'>"episode-based"</span>, <span class='st'>"patient-based"</span>, <span class='st'>"isolate-based"</span><span class='op'>)</span>,
ignore_I <span class='op'>=</span> <span class='cn'>TRUE</span>,
points_threshold <span class='op'>=</span> <span class='fl'>2</span>,
info <span class='op'>=</span> <span class='fu'><a href='https://rdrr.io/r/base/interactive.html'>interactive</a></span><span class='op'>(</span><span class='op'>)</span>,
@ -269,6 +270,7 @@
col_date <span class='op'>=</span> <span class='cn'>NULL</span>,
col_patient_id <span class='op'>=</span> <span class='cn'>NULL</span>,
col_mo <span class='op'>=</span> <span class='cn'>NULL</span>,
method <span class='op'>=</span> <span class='st'>"episode-based"</span>,
<span class='va'>...</span>
<span class='op'>)</span>
@ -277,7 +279,7 @@
col_date <span class='op'>=</span> <span class='cn'>NULL</span>,
col_patient_id <span class='op'>=</span> <span class='cn'>NULL</span>,
col_mo <span class='op'>=</span> <span class='cn'>NULL</span>,
col_keyantibiotics <span class='op'>=</span> <span class='cn'>NULL</span>,
method <span class='op'>=</span> <span class='st'>"phenotype-based"</span>,
<span class='va'>...</span>
<span class='op'>)</span></pre>
@ -313,8 +315,8 @@
<td><p>column name of the logicals (<code>TRUE</code>/<code>FALSE</code>) whether a ward or department is an Intensive Care Unit (ICU)</p></td>
</tr>
<tr>
<th>col_keyantibiotics</th>
<td><p>column name of the key antibiotics to determine first (weighted) isolates, see <code><a href='key_antibiotics.html'>key_antibiotics()</a></code>. Defaults to the first column that starts with 'key' followed by 'ab' or 'antibiotics' (case insensitive). Use <code>col_keyantibiotics = FALSE</code> to prevent this. Can also be the output of <code><a href='key_antibiotics.html'>key_antibiotics()</a></code>.</p></td>
<th>col_keyantimicrobials</th>
<td><p>(only useful when <code>method = "phenotype-based"</code>) column name of the key antimicrobials to determine first (weighted) isolates, see <code><a href='key_antimicrobials.html'>key_antimicrobials()</a></code>. Defaults to the first column that starts with 'key' followed by 'ab' or 'antibiotics' or 'antimicrobials' (case insensitive). Use <code>col_keyantimicrobials = FALSE</code> to prevent this. Can also be the output of <code><a href='key_antimicrobials.html'>key_antimicrobials()</a></code>.</p></td>
</tr>
<tr>
<th>episode_days</th>
@ -334,15 +336,19 @@
</tr>
<tr>
<th>type</th>
<td><p>type to determine weighed isolates; can be <code>"keyantibiotics"</code> or <code>"points"</code>, see <em>Details</em></p></td>
<td><p>type to determine weighed isolates; can be <code>"keyantimicrobials"</code> or <code>"points"</code>, see <em>Details</em></p></td>
</tr>
<tr>
<th>method</th>
<td><p>the algorithm to apply, either <code>"phenotype-based"</code>, <code>"episode-based"</code>, <code>"patient-based"</code> or <code>"isolate-based"</code> (can be abbreviated), see <em>Details</em></p></td>
</tr>
<tr>
<th>ignore_I</th>
<td><p>logical to indicate whether antibiotic interpretations with <code>"I"</code> will be ignored when <code>type = "keyantibiotics"</code>, see <em>Details</em></p></td>
<td><p>logical to indicate whether antibiotic interpretations with <code>"I"</code> will be ignored when <code>type = "keyantimicrobials"</code>, see <em>Details</em></p></td>
</tr>
<tr>
<th>points_threshold</th>
<td><p>points until the comparison of key antibiotics will lead to inclusion of an isolate when <code>type = "points"</code>, see <em>Details</em></p></td>
<td><p>minimum number of points to require before differences in the antibiogram will lead to inclusion of an isolate when <code>type = "points"</code>, see <em>Details</em></p></td>
</tr>
<tr>
<th>info</th>
@ -358,7 +364,7 @@
</tr>
<tr>
<th>...</th>
<td><p>arguments passed on to <code>first_isolate()</code> when using <code>filter_first_isolate()</code>, or arguments passed on to <code><a href='key_antibiotics.html'>key_antibiotics()</a></code> when using <code>filter_first_weighted_isolate()</code></p></td>
<td><p>arguments passed on to <code>first_isolate()</code> when using <code>filter_first_isolate()</code>, or arguments passed on to <code><a href='key_antimicrobials.html'>key_antimicrobials()</a></code> otherwise (such as <code>universal</code>, <code>gram_negative</code>, <code>gram_positive</code>)</p></td>
</tr>
</table>
@ -371,42 +377,69 @@
<p>A <code><a href='https://rdrr.io/r/base/logical.html'>logical</a></code> vector</p>
<h2 class="hasAnchor" id="details"><a class="anchor" href="#details"></a>Details</h2>
<p>These functions are context-aware. This means that then the <code>x</code> argument can be left blank, see <em>Examples</em>.</p>
<p>To conduct epidemiological analyses on antimicrobial resistance data, only so-called first isolates should be included to prevent overestimation and underestimation of antimicrobial resistance. Different algorithms can be used to do so, see below.</p>
<p>These functions are context-aware. This means that then the <code>x</code> argument can be left blank, see <em>Examples</em>.</p>
<p>The <code>first_isolate()</code> function is a wrapper around the <code><a href='get_episode.html'>is_new_episode()</a></code> function, but more efficient for data sets containing microorganism codes or names.</p>
<p>All isolates with a microbial ID of <code>NA</code> will be excluded as first isolate.</p><h3 class='hasAnchor' id='arguments'><a class='anchor' href='#arguments'></a>Why this is so Important</h3>
<p>All isolates with a microbial ID of <code>NA</code> will be excluded as first isolate.</p><h3 class='hasAnchor' id='arguments'><a class='anchor' href='#arguments'></a>Different algorithms</h3>
<p>To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode <a href='https://pubmed.ncbi.nlm.nih.gov/17304462/'>(Hindler <em>et al.</em> 2007)</a>. If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all <em>S. aureus</em> isolates would be overestimated, because you included this MRSA more than once. It would be <a href='https://en.wikipedia.org/wiki/Selection_bias'>selection bias</a>.</p>
<h3 class='hasAnchor' id='arguments'><a class='anchor' href='#arguments'></a><code>filter_*()</code> Shortcuts</h3>
<p>According to Hindler <em>et al.</em> (2007, doi: <a href='https://doi.org/10.1086/511864'>10.1086/511864</a>
), there are different algorithms to select first isolates with increasing reliability: isolate-based, patient-based, episode-based and phenotype-based. All algorithms select on a combination of the taxonomic genus and species (not subspecies).</p>
<p>All mentioned algorithms are covered in the <code>first_isolate()</code> function:</p><table class='table'>
<tr><td><strong>Algorithm</strong></td><td><strong>Function to apply</strong></td></tr>
<tr><td>Isolate-based</td><td><code>first_isolate(x, method = "isolate-based")</code></td></tr>
<tr><td><em>(= all isolates)</em></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td>Patient-based</td><td><code>first_isolate(x, method = "patient-based")</code></td></tr>
<tr><td><em>(= first isolate per patient)</em></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td>Episode-based</td><td><code>first_isolate(x, method = "episode-based")</code>, or:</td></tr>
<tr><td><em>(= first isolate per episode)</em></td><td></td></tr>
<tr><td>- 7-Day interval from initial isolate</td><td>- <code>first_isolate(x, method = "e", episode_days = 7)</code></td></tr>
<tr><td>- 30-Day interval from initial isolate</td><td>- <code>first_isolate(x, method = "e", episode_days = 30)</code></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td>Phenotype-based</td><td><code>first_isolate(x, method = "phenotype-based")</code>, or:</td></tr>
<tr><td><em>(= first isolate per phenotype)</em></td><td></td></tr>
<tr><td>- Major difference in any antimicrobial result</td><td>- <code>first_isolate(x, type = "points")</code></td></tr>
<tr><td>- Any difference in key antimicrobial results</td><td>- <code>first_isolate(x, type = "keyantimicrobials")</code></td></tr>
</table>
<p>The functions <code>filter_first_isolate()</code> and <code>filter_first_weighted_isolate()</code> are helper functions to quickly filter on first isolates.</p>
<p>The function <code>filter_first_isolate()</code> is essentially equal to either:</p><pre> <span class='va'>x</span><span class='op'>[</span><span class='fu'>first_isolate</span><span class='op'>(</span><span class='va'>x</span>, <span class='va'>...</span><span class='op'>)</span>, <span class='op'>]</span>
<span class='va'>x</span> <span class='op'>%&gt;%</span> <span class='fu'><a href='https://dplyr.tidyverse.org/reference/filter.html'>filter</a></span><span class='op'>(</span><span class='fu'>first_isolate</span><span class='op'>(</span><span class='va'>...</span><span class='op'>)</span><span class='op'>)</span>
</pre>
<p>The function <code>filter_first_weighted_isolate()</code> is essentially equal to:</p><pre> <span class='va'>x</span> <span class='op'>%&gt;%</span>
<span class='fu'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='op'>(</span>keyab <span class='op'>=</span> <span class='fu'><a href='key_antibiotics.html'>key_antibiotics</a></span><span class='op'>(</span><span class='va'>.</span><span class='op'>)</span><span class='op'>)</span> <span class='op'>%&gt;%</span>
<span class='fu'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='op'>(</span>only_weighted_firsts <span class='op'>=</span> <span class='fu'>first_isolate</span><span class='op'>(</span><span class='va'>x</span>,
col_keyantibiotics <span class='op'>=</span> <span class='st'>"keyab"</span>, <span class='va'>...</span><span class='op'>)</span><span class='op'>)</span> <span class='op'>%&gt;%</span>
<span class='fu'><a href='https://dplyr.tidyverse.org/reference/filter.html'>filter</a></span><span class='op'>(</span><span class='va'>only_weighted_firsts</span> <span class='op'>==</span> <span class='cn'>TRUE</span><span class='op'>)</span> <span class='op'>%&gt;%</span>
<span class='fu'><a href='https://dplyr.tidyverse.org/reference/select.html'>select</a></span><span class='op'>(</span><span class='op'>-</span><span class='va'>only_weighted_firsts</span>, <span class='op'>-</span><span class='va'>keyab</span><span class='op'>)</span>
</pre>
<h4 class='hasAnchor' id='arguments'><a class='anchor' href='#arguments'></a>Isolate-based</h4>
<h2 class="hasAnchor" id="key-antibiotics"><a class="anchor" href="#key-antibiotics"></a>Key Antibiotics</h2>
<p>This algorithm does not require any selection, as all isolates should be included. It does, however, respect all arguments set in the <code>first_isolate()</code> function. For example, the default setting for <code>include_unknown</code> (<code>FALSE</code>) will omit selection of rows without a microbial ID.</p>
<h4 class='hasAnchor' id='arguments'><a class='anchor' href='#arguments'></a>Patient-based</h4>
<p>There are two ways to determine whether isolates can be included as first weighted isolates which will give generally the same results:</p><ol>
<li><p>Using <code>type = "keyantibiotics"</code> and argument <code>ignore_I</code></p>
<p>Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With <code>ignore_I = FALSE</code>, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. Read more about this in the <code><a href='key_antibiotics.html'>key_antibiotics()</a></code> function.</p></li>
<p>To include every genus-species combination per patient once, set the <code>episode_days</code> to <code>Inf</code>. Although often inappropriate, this algorithm makes sure that no duplicate isolates are selected from the same patient.</p>
<h4 class='hasAnchor' id='arguments'><a class='anchor' href='#arguments'></a>Episode-based</h4>
<p>To include every genus-species combination per patient episode once, set the <code>episode_days</code> to a sensible number of days. Depending on the type of analysis, this could be 14, 30, 60 or 365. Short episodes are common for analysing specific hospital or ward data, long episodes are common for analysing regional and national data.</p>
<p>This is the most common algorithm to correct for duplicate isolates. Patients are categorised into episodes based on their ID and dates (e.g., the date of specimen receipt or laboratory result). While this is a common algorithm, it does not take into account antimicrobial test results. This means that e.g. a methicillin-resistant <em>Staphylococcus aureus</em> (MRSA) isolate cannot be differentiated from a wildtype <em>Staphylococcus aureus</em> isolate.</p>
<h4 class='hasAnchor' id='arguments'><a class='anchor' href='#arguments'></a>Phenotype-based</h4>
<p>This is a more reliable algorithm, since it also <em>weighs</em> the antibiogram (antimicrobial test results) yielding so-called 'first weighted isolates'. There are two different methods to weigh the antibiogram:</p><ol>
<li><p>Using <code>type = "points"</code> and argument <code>points_threshold</code></p>
<p>A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds <code>points_threshold</code>, which defaults to <code>2</code>, an isolate will be (re)selected as a first weighted isolate.</p></li>
<p>This method weighs <em>all</em> antimicrobial agents available in the data set. Any difference from I to S or R (or vice versa) counts as 0.5 points, a difference from S to R (or vice versa) counts as 1 point. When the sum of points exceeds <code>points_threshold</code>, which defaults to <code>2</code>, an isolate will be selected as a first weighted isolate.</p>
<p>All antimicrobials are internally selected using the <code><a href='key_antimicrobials.html'>all_antimicrobials()</a></code> function. The output of this function does not need to be passed to the <code>first_isolate()</code> function.</p></li>
<li><p>Using <code>type = "keyantimicrobials"</code> and argument <code>ignore_I</code></p>
<p>This method only weighs specific antimicrobial agents, called <em>key antimicrobials</em>. Any difference from S to R (or vice versa) in these key antimicrobials will select an isolate as a first weighted isolate. With <code>ignore_I = FALSE</code>, also differences from I to S or R (or vice versa) will lead to this.</p>
<p>Key antimicrobials are internally selected using the <code><a href='key_antimicrobials.html'>key_antimicrobials()</a></code> function, but can also be added manually as a variable to the data and set in the <code>col_keyantimicrobials</code> argument. Another option is to pass the output of the <code><a href='key_antimicrobials.html'>key_antimicrobials()</a></code> function directly to the <code>col_keyantimicrobials</code> argument.</p></li>
</ol>
<p>The default algorithm is phenotype-based (using <code>type = "points"</code>) and episode-based (using <code>episode_days = 365</code>). This makes sure that every genus-species combination is selected per patient once per year, while taking into account all antimicrobial test results.</p>
<h2 class="hasAnchor" id="stable-lifecycle"><a class="anchor" href="#stable-lifecycle"></a>Stable Lifecycle</h2>
@ -421,14 +454,13 @@ The <a href='lifecycle.html'>lifecycle</a> of this function is <strong>stable</s
<p>On our website <a href='https://msberends.github.io/AMR/'>https://msberends.github.io/AMR/</a> you can find <a href='https://msberends.github.io/AMR/articles/AMR.html'>a comprehensive tutorial</a> about how to conduct AMR data analysis, the <a href='https://msberends.github.io/AMR/reference/'>complete documentation of all functions</a> and <a href='https://msberends.github.io/AMR/articles/WHONET.html'>an example analysis using WHONET data</a>. As we would like to better understand the backgrounds and needs of our users, please <a href='https://msberends.github.io/AMR/survey.html'>participate in our survey</a>!</p>
<h2 class="hasAnchor" id="see-also"><a class="anchor" href="#see-also"></a>See also</h2>
<div class='dont-index'><p><code><a href='key_antibiotics.html'>key_antibiotics()</a></code></p></div>
<div class='dont-index'><p><code><a href='key_antimicrobials.html'>key_antimicrobials()</a></code></p></div>
<h2 class="hasAnchor" id="examples"><a class="anchor" href="#examples"></a>Examples</h2>
<pre class="examples"><span class='co'># `example_isolates` is a data set available in the AMR package.</span>
<span class='co'># See ?example_isolates.</span>
<span class='va'>example_isolates</span><span class='op'>[</span><span class='fu'>first_isolate</span><span class='op'>(</span><span class='va'>example_isolates</span><span class='op'>)</span>, <span class='op'>]</span>
<span class='co'># \donttest{</span>
<span class='co'># faster way, only works in R 3.2 and later:</span>
<span class='va'>example_isolates</span><span class='op'>[</span><span class='fu'>first_isolate</span><span class='op'>(</span><span class='op'>)</span>, <span class='op'>]</span>
@ -466,7 +498,7 @@ The <a href='lifecycle.html'>lifecycle</a> of this function is <strong>stable</s
<span class='co'># Have a look at A and B.</span>
<span class='co'># B is more reliable because every isolate is counted only once.</span>
<span class='co'># Gentamicin resistance in hospital D appears to be 3.7% higher than</span>
<span class='co'># Gentamicin resistance in hospital D appears to be 4.2% higher than</span>
<span class='co'># when you (erroneously) would have used all isolates for analysis.</span>
<span class='op'>}</span>
<span class='co'># }</span>

View File

@ -81,7 +81,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>
@ -496,9 +496,9 @@
</tr><tr>
<td>
<p><code><a href="key_antibiotics.html">key_antibiotics()</a></code> <code><a href="key_antibiotics.html">key_antibiotics_equal()</a></code> </p>
<p><code><a href="AMR-deprecated.html">p_symbol()</a></code> <code><a href="AMR-deprecated.html">key_antibiotics()</a></code> <code><a href="AMR-deprecated.html">key_antibiotics_equal()</a></code> </p>
</td>
<td><p>Key Antibiotics for First (Weighted) Isolates</p></td>
<td><p>Deprecated Functions</p></td>
</tr><tr>
<td>
@ -667,7 +667,7 @@
<tr>
<td>
<p><code><a href="AMR-deprecated.html">p_symbol()</a></code> </p>
<p><code><a href="AMR-deprecated.html">p_symbol()</a></code> <code><a href="AMR-deprecated.html">key_antibiotics()</a></code> <code><a href="AMR-deprecated.html">key_antibiotics_equal()</a></code> </p>
</td>
<td><p>Deprecated Functions</p></td>
</tr>

View File

@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Key Antibiotics for First (Weighted) Isolates — key_antibiotics • AMR (for R)</title>
<title>(Key) Antimicrobials for First Weighted Isolates — key_antimicrobials • AMR (for R)</title>
<!-- favicons -->
<link rel="icon" type="image/png" sizes="16x16" href="../favicon-16x16.png">
@ -48,8 +48,8 @@
<link href="../extra.css" rel="stylesheet">
<script src="../extra.js"></script>
<meta property="og:title" content="Key Antibiotics for First (Weighted) Isolates — key_antibiotics" />
<meta property="og:description" content="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." />
<meta property="og:title" content="(Key) Antimicrobials for First Weighted Isolates — key_antimicrobials" />
<meta property="og:description" content="These functions can be used to determine first weighted isolates by considering the phenotype for isolate selection (see first_isolate()). Using a phenotype-based method to determine first isolates is more reliable than methods that disregard phenotypes." />
<meta property="og:image" content="https://msberends.github.io/AMR/logo.png" />
@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>
@ -233,48 +233,39 @@
<div class="row">
<div class="col-md-9 contents">
<div class="page-header">
<h1>Key Antibiotics for First (Weighted) Isolates</h1>
<small class="dont-index">Source: <a href='https://github.com/msberends/AMR/blob/master/R/key_antibiotics.R'><code>R/key_antibiotics.R</code></a></small>
<div class="hidden name"><code>key_antibiotics.Rd</code></div>
<h1>(Key) Antimicrobials for First Weighted Isolates</h1>
<small class="dont-index">Source: <a href='https://github.com/msberends/AMR/blob/master/R/key_antimicrobials.R'><code>R/key_antimicrobials.R</code></a></small>
<div class="hidden name"><code>key_antimicrobials.Rd</code></div>
</div>
<div class="ref-description">
<p>These function can be used to determine first isolates (see <code><a href='first_isolate.html'>first_isolate()</a></code>). Using key antibiotics to determine first isolates is more reliable than without key antibiotics. These selected isolates can then be called first 'weighted' isolates.</p>
<p>These functions can be used to determine first weighted isolates by considering the phenotype for isolate selection (see <code><a href='first_isolate.html'>first_isolate()</a></code>). Using a phenotype-based method to determine first isolates is more reliable than methods that disregard phenotypes.</p>
</div>
<pre class="usage"><span class='fu'>key_antibiotics</span><span class='op'>(</span>
<pre class="usage"><span class='fu'>key_antimicrobials</span><span class='op'>(</span>
x <span class='op'>=</span> <span class='cn'>NULL</span>,
col_mo <span class='op'>=</span> <span class='cn'>NULL</span>,
universal_1 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"amoxicillin"</span><span class='op'>)</span>,
universal_2 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"amoxicillin/clavulanic acid"</span><span class='op'>)</span>,
universal_3 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"cefuroxime"</span><span class='op'>)</span>,
universal_4 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"piperacillin/tazobactam"</span><span class='op'>)</span>,
universal_5 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"ciprofloxacin"</span><span class='op'>)</span>,
universal_6 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"trimethoprim/sulfamethoxazole"</span><span class='op'>)</span>,
GramPos_1 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"vancomycin"</span><span class='op'>)</span>,
GramPos_2 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"teicoplanin"</span><span class='op'>)</span>,
GramPos_3 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"tetracycline"</span><span class='op'>)</span>,
GramPos_4 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"erythromycin"</span><span class='op'>)</span>,
GramPos_5 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"oxacillin"</span><span class='op'>)</span>,
GramPos_6 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"rifampin"</span><span class='op'>)</span>,
GramNeg_1 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"gentamicin"</span><span class='op'>)</span>,
GramNeg_2 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"tobramycin"</span><span class='op'>)</span>,
GramNeg_3 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"colistin"</span><span class='op'>)</span>,
GramNeg_4 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"cefotaxime"</span><span class='op'>)</span>,
GramNeg_5 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"ceftazidime"</span><span class='op'>)</span>,
GramNeg_6 <span class='op'>=</span> <span class='fu'><a href='guess_ab_col.html'>guess_ab_col</a></span><span class='op'>(</span><span class='va'>x</span>, <span class='st'>"meropenem"</span><span class='op'>)</span>,
warnings <span class='op'>=</span> <span class='cn'>TRUE</span>,
universal <span class='op'>=</span> <span class='fu'><a href='https://rdrr.io/r/base/c.html'>c</a></span><span class='op'>(</span><span class='st'>"ampicillin"</span>, <span class='st'>"amoxicillin/clavulanic acid"</span>, <span class='st'>"cefuroxime"</span>,
<span class='st'>"piperacillin/tazobactam"</span>, <span class='st'>"ciprofloxacin"</span>, <span class='st'>"trimethoprim/sulfamethoxazole"</span><span class='op'>)</span>,
gram_negative <span class='op'>=</span> <span class='fu'><a href='https://rdrr.io/r/base/c.html'>c</a></span><span class='op'>(</span><span class='st'>"gentamicin"</span>, <span class='st'>"tobramycin"</span>, <span class='st'>"colistin"</span>, <span class='st'>"cefotaxime"</span>,
<span class='st'>"ceftazidime"</span>, <span class='st'>"meropenem"</span><span class='op'>)</span>,
gram_positive <span class='op'>=</span> <span class='fu'><a href='https://rdrr.io/r/base/c.html'>c</a></span><span class='op'>(</span><span class='st'>"vancomycin"</span>, <span class='st'>"teicoplanin"</span>, <span class='st'>"tetracycline"</span>, <span class='st'>"erythromycin"</span>,
<span class='st'>"oxacillin"</span>, <span class='st'>"rifampin"</span><span class='op'>)</span>,
antifungal <span class='op'>=</span> <span class='fu'><a href='https://rdrr.io/r/base/c.html'>c</a></span><span class='op'>(</span><span class='st'>"anidulafungin"</span>, <span class='st'>"caspofungin"</span>, <span class='st'>"fluconazole"</span>, <span class='st'>"miconazole"</span>,
<span class='st'>"nystatin"</span>, <span class='st'>"voriconazole"</span><span class='op'>)</span>,
only_rsi_columns <span class='op'>=</span> <span class='cn'>FALSE</span>,
<span class='va'>...</span>
<span class='op'>)</span>
<span class='fu'>key_antibiotics_equal</span><span class='op'>(</span>
<span class='fu'>all_antimicrobials</span><span class='op'>(</span>x <span class='op'>=</span> <span class='cn'>NULL</span>, only_rsi_columns <span class='op'>=</span> <span class='cn'>FALSE</span>, <span class='va'>...</span><span class='op'>)</span>
<span class='fu'>antimicrobials_equal</span><span class='op'>(</span>
<span class='va'>y</span>,
<span class='va'>z</span>,
type <span class='op'>=</span> <span class='fu'><a href='https://rdrr.io/r/base/c.html'>c</a></span><span class='op'>(</span><span class='st'>"keyantibiotics"</span>, <span class='st'>"points"</span><span class='op'>)</span>,
type <span class='op'>=</span> <span class='fu'><a href='https://rdrr.io/r/base/c.html'>c</a></span><span class='op'>(</span><span class='st'>"points"</span>, <span class='st'>"keyantimicrobials"</span><span class='op'>)</span>,
ignore_I <span class='op'>=</span> <span class='cn'>TRUE</span>,
points_threshold <span class='op'>=</span> <span class='fl'>2</span>,
info <span class='op'>=</span> <span class='cn'>FALSE</span>,
na.rm <span class='op'>=</span> <span class='cn'>TRUE</span>,
<span class='va'>...</span>
<span class='op'>)</span></pre>
@ -290,24 +281,24 @@
<td><p>column name of the IDs of the microorganisms (see <code><a href='as.mo.html'>as.mo()</a></code>), defaults to the first column of class <code><a href='as.mo.html'>mo</a></code>. Values will be coerced using <code><a href='as.mo.html'>as.mo()</a></code>.</p></td>
</tr>
<tr>
<th>universal_1, universal_2, universal_3, universal_4, universal_5, universal_6</th>
<td><p>column names of <strong>broad-spectrum</strong> antibiotics, case-insensitive. See details for which antibiotics will be used at default (which are guessed with <code><a href='guess_ab_col.html'>guess_ab_col()</a></code>).</p></td>
<th>universal</th>
<td><p>names of <strong>broad-spectrum</strong> antimicrobial agents, case-insensitive. Set to <code>NULL</code> to ignore. See <em>Details</em> for the default agents.</p></td>
</tr>
<tr>
<th>GramPos_1, GramPos_2, GramPos_3, GramPos_4, GramPos_5, GramPos_6</th>
<td><p>column names of antibiotics for <strong>Gram-positives</strong>, case-insensitive. See details for which antibiotics will be used at default (which are guessed with <code><a href='guess_ab_col.html'>guess_ab_col()</a></code>).</p></td>
<th>gram_negative</th>
<td><p>names of antibiotic agents for <strong>Gram-positives</strong>, case-insensitive. Set to <code>NULL</code> to ignore. See <em>Details</em> for the default agents.</p></td>
</tr>
<tr>
<th>GramNeg_1, GramNeg_2, GramNeg_3, GramNeg_4, GramNeg_5, GramNeg_6</th>
<td><p>column names of antibiotics for <strong>Gram-negatives</strong>, case-insensitive. See details for which antibiotics will be used at default (which are guessed with <code><a href='guess_ab_col.html'>guess_ab_col()</a></code>).</p></td>
<th>gram_positive</th>
<td><p>names of antibiotic agents for <strong>Gram-negatives</strong>, case-insensitive. Set to <code>NULL</code> to ignore. See <em>Details</em> for the default agents.</p></td>
</tr>
<tr>
<th>warnings</th>
<td><p>give a warning about missing antibiotic columns (they will be ignored)</p></td>
<th>antifungal</th>
<td><p>names of antifungal agents for <strong>fungi</strong>, case-insensitive. Set to <code>NULL</code> to ignore. See <em>Details</em> for the default agents.</p></td>
</tr>
<tr>
<th>...</th>
<td><p>other arguments passed on to functions</p></td>
<td><p>ignored, allows for future extensions</p></td>
</tr>
<tr>
<th>y, z</th>
@ -315,62 +306,63 @@
</tr>
<tr>
<th>type</th>
<td><p>type to determine weighed isolates; can be <code>"keyantibiotics"</code> or <code>"points"</code>, see <em>Details</em></p></td>
<td><p>type to determine weighed isolates; can be <code>"keyantimicrobials"</code> or <code>"points"</code>, see <em>Details</em></p></td>
</tr>
<tr>
<th>ignore_I</th>
<td><p>logical to indicate whether antibiotic interpretations with <code>"I"</code> will be ignored when <code>type = "keyantibiotics"</code>, see <em>Details</em></p></td>
<td><p>logical to indicate whether antibiotic interpretations with <code>"I"</code> will be ignored when <code>type = "keyantimicrobials"</code>, see <em>Details</em></p></td>
</tr>
<tr>
<th>points_threshold</th>
<td><p>points until the comparison of key antibiotics will lead to inclusion of an isolate when <code>type = "points"</code>, see <em>Details</em></p></td>
<td><p>minimum number of points to require before differences in the antibiogram will lead to inclusion of an isolate when <code>type = "points"</code>, see <em>Details</em></p></td>
</tr>
<tr>
<th>info</th>
<td><p>unused - previously used to indicate whether a progress bar should print</p></td>
</tr>
<tr>
<th>na.rm</th>
<td><p>a <a href='https://rdrr.io/r/base/logical.html'>logical</a> to indicate whether comparison with <code>NA</code> should return <code>FALSE</code> (defaults to <code>TRUE</code> for backwards compatibility)</p></td>
</tr>
</table>
<h2 class="hasAnchor" id="details"><a class="anchor" href="#details"></a>Details</h2>
<p>The <code>key_antibiotics()</code> function is context-aware. This means that then the <code>x</code> argument can be left blank, see <em>Examples</em>.</p>
<p>The function <code>key_antibiotics()</code> returns a character vector with 12 antibiotic results for every isolate. These isolates can then be compared using <code>key_antibiotics_equal()</code>, to check if two isolates have generally the same antibiogram. Missing and invalid values are replaced with a dot (<code>"."</code>) by <code>key_antibiotics()</code> and ignored by <code>key_antibiotics_equal()</code>.</p>
<p>The <code><a href='first_isolate.html'>first_isolate()</a></code> 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 <em>S. aureus</em> (MSSA) is found within the same patient episode. Without key antibiotic comparison it would not. See <code><a href='first_isolate.html'>first_isolate()</a></code> for more info.</p>
<p>At default, the antibiotics that are used for <strong>Gram-positive bacteria</strong> are:</p><ul>
<li><p>Amoxicillin</p></li>
<p>The <code>key_antimicrobials()</code> and <code>all_antimicrobials()</code> functions are context-aware. This means that then the <code>x</code> argument can be left blank, see <em>Examples</em>.</p>
<p>The function <code>key_antimicrobials()</code> returns a character vector with 12 antimicrobial results for every isolate. The function <code>all_antimicrobials()</code> returns a character vector with all antimicrobial results for every isolate. These vectors can then be compared using <code>antimicrobials_equal()</code>, to check if two isolates have generally the same antibiogram. Missing and invalid values are replaced with a dot (<code>"."</code>) by <code>key_antimicrobials()</code> and ignored by <code>antimicrobials_equal()</code>.</p>
<p>Please see the <code><a href='first_isolate.html'>first_isolate()</a></code> function how these important functions enable the 'phenotype-based' method for determination of first isolates.</p>
<p>The default antimicrobial agents used for <strong>all rows</strong> (set in <code>universal</code>) are:</p><ul>
<li><p>Ampicillin</p></li>
<li><p>Amoxicillin/clavulanic acid</p></li>
<li><p>Cefuroxime</p></li>
<li><p>Piperacillin/tazobactam</p></li>
<li><p>Ciprofloxacin</p></li>
<li><p>Piperacillin/tazobactam</p></li>
<li><p>Trimethoprim/sulfamethoxazole</p></li>
<li><p>Vancomycin</p></li>
<li><p>Teicoplanin</p></li>
<li><p>Tetracycline</p></li>
</ul>
<p>The default antimicrobial agents used for <strong>Gram-negative bacteria</strong> (set in <code>gram_negative</code>) are:</p><ul>
<li><p>Cefotaxime</p></li>
<li><p>Ceftazidime</p></li>
<li><p>Colistin</p></li>
<li><p>Gentamicin</p></li>
<li><p>Meropenem</p></li>
<li><p>Tobramycin</p></li>
</ul>
<p>The default antimicrobial agents used for <strong>Gram-positive bacteria</strong> (set in <code>gram_positive</code>) are:</p><ul>
<li><p>Erythromycin</p></li>
<li><p>Oxacillin</p></li>
<li><p>Rifampin</p></li>
<li><p>Teicoplanin</p></li>
<li><p>Tetracycline</p></li>
<li><p>Vancomycin</p></li>
</ul>
<p>At default the antibiotics that are used for <strong>Gram-negative bacteria</strong> are:</p><ul>
<li><p>Amoxicillin</p></li>
<li><p>Amoxicillin/clavulanic acid</p></li>
<li><p>Cefuroxime</p></li>
<li><p>Piperacillin/tazobactam</p></li>
<li><p>Ciprofloxacin</p></li>
<li><p>Trimethoprim/sulfamethoxazole</p></li>
<li><p>Gentamicin</p></li>
<li><p>Tobramycin</p></li>
<li><p>Colistin</p></li>
<li><p>Cefotaxime</p></li>
<li><p>Ceftazidime</p></li>
<li><p>Meropenem</p></li>
<p>The default antimicrobial agents used for <strong>fungi</strong> (set in <code>antifungal</code>) are:</p><ul>
<li><p>Anidulafungin</p></li>
<li><p>Caspofungin</p></li>
<li><p>Fluconazole</p></li>
<li><p>Miconazole</p></li>
<li><p>Nystatin</p></li>
<li><p>Voriconazole</p></li>
</ul>
<p>The function <code>key_antibiotics_equal()</code> checks the characters returned by <code>key_antibiotics()</code> for equality, and returns a <code><a href='https://rdrr.io/r/base/logical.html'>logical</a></code> vector.</p>
<h2 class="hasAnchor" id="stable-lifecycle"><a class="anchor" href="#stable-lifecycle"></a>Stable Lifecycle</h2>
@ -378,17 +370,6 @@
<p><img src='figures/lifecycle_stable.svg' style=margin-bottom:5px /> <br />
The <a href='lifecycle.html'>lifecycle</a> of this function is <strong>stable</strong>. In a stable function, major changes are unlikely. This means that the unlying code will generally evolve by adding new arguments; removing arguments or changing the meaning of existing arguments will be avoided.</p>
<p>If the unlying code needs breaking changes, they will occur gradually. For example, a argument will be deprecated and first continue to work, but will emit an message informing you of the change. Next, typically after at least one newly released version on CRAN, the message will be transformed to an error.</p>
<h2 class="hasAnchor" id="key-antibiotics"><a class="anchor" href="#key-antibiotics"></a>Key Antibiotics</h2>
<p>There are two ways to determine whether isolates can be included as first weighted isolates which will give generally the same results:</p><ol>
<li><p>Using <code>type = "keyantibiotics"</code> and argument <code>ignore_I</code></p>
<p>Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With <code>ignore_I = FALSE</code>, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. Read more about this in the <code>key_antibiotics()</code> function.</p></li>
<li><p>Using <code>type = "points"</code> and argument <code>points_threshold</code></p>
<p>A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds <code>points_threshold</code>, which defaults to <code>2</code>, an isolate will be (re)selected as a first weighted isolate.</p></li>
</ol>
<h2 class="hasAnchor" id="read-more-on-our-website-"><a class="anchor" href="#read-more-on-our-website-"></a>Read more on Our Website!</h2>
@ -402,30 +383,30 @@ The <a href='lifecycle.html'>lifecycle</a> of this function is <strong>stable</s
<pre class="examples"><span class='co'># `example_isolates` is a data set available in the AMR package.</span>
<span class='co'># See ?example_isolates.</span>
<span class='co'># output of the `key_antibiotics()` function could be like this:</span>
<span class='co'># output of the `key_antimicrobials()` function could be like this:</span>
<span class='va'>strainA</span> <span class='op'>&lt;-</span> <span class='st'>"SSSRR.S.R..S"</span>
<span class='va'>strainB</span> <span class='op'>&lt;-</span> <span class='st'>"SSSIRSSSRSSS"</span>
<span class='co'># those strings can be compared with:</span>
<span class='fu'>key_antibiotics_equal</span><span class='op'>(</span><span class='va'>strainA</span>, <span class='va'>strainB</span><span class='op'>)</span>
<span class='fu'>antimicrobials_equal</span><span class='op'>(</span><span class='va'>strainA</span>, <span class='va'>strainB</span>, type <span class='op'>=</span> <span class='st'>"keyantimicrobials"</span><span class='op'>)</span>
<span class='co'># TRUE, because I is ignored (as well as missing values)</span>
<span class='fu'>key_antibiotics_equal</span><span class='op'>(</span><span class='va'>strainA</span>, <span class='va'>strainB</span>, ignore_I <span class='op'>=</span> <span class='cn'>FALSE</span><span class='op'>)</span>
<span class='fu'>antimicrobials_equal</span><span class='op'>(</span><span class='va'>strainA</span>, <span class='va'>strainB</span>, type <span class='op'>=</span> <span class='st'>"keyantimicrobials"</span>, ignore_I <span class='op'>=</span> <span class='cn'>FALSE</span><span class='op'>)</span>
<span class='co'># FALSE, because I is not ignored and so the 4th character differs</span>
<span class='co'># \donttest{</span>
<span class='kw'>if</span> <span class='op'>(</span><span class='kw'><a href='https://rdrr.io/r/base/library.html'>require</a></span><span class='op'>(</span><span class='st'><a href='https://dplyr.tidyverse.org'>"dplyr"</a></span><span class='op'>)</span><span class='op'>)</span> <span class='op'>{</span>
<span class='co'># set key antibiotics to a new variable</span>
<span class='va'>my_patients</span> <span class='op'>&lt;-</span> <span class='va'>example_isolates</span> <span class='op'>%&gt;%</span>
<span class='fu'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='op'>(</span>keyab <span class='op'>=</span> <span class='fu'>key_antibiotics</span><span class='op'>(</span><span class='op'>)</span><span class='op'>)</span> <span class='op'>%&gt;%</span> <span class='co'># no need to define `x`</span>
<span class='fu'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='op'>(</span>keyab <span class='op'>=</span> <span class='fu'>key_antimicrobials</span><span class='op'>(</span>antifungal <span class='op'>=</span> <span class='cn'>NULL</span><span class='op'>)</span><span class='op'>)</span> <span class='op'>%&gt;%</span> <span class='co'># no need to define `x`</span>
<span class='fu'><a href='https://dplyr.tidyverse.org/reference/mutate.html'>mutate</a></span><span class='op'>(</span>
<span class='co'># now calculate first isolates</span>
first_regular <span class='op'>=</span> <span class='fu'><a href='first_isolate.html'>first_isolate</a></span><span class='op'>(</span>col_keyantibiotics <span class='op'>=</span> <span class='cn'>FALSE</span><span class='op'>)</span>,
first_regular <span class='op'>=</span> <span class='fu'><a href='first_isolate.html'>first_isolate</a></span><span class='op'>(</span>col_keyantimicrobials <span class='op'>=</span> <span class='cn'>FALSE</span><span class='op'>)</span>,
<span class='co'># and first WEIGHTED isolates</span>
first_weighted <span class='op'>=</span> <span class='fu'><a href='first_isolate.html'>first_isolate</a></span><span class='op'>(</span>col_keyantibiotics <span class='op'>=</span> <span class='st'>"keyab"</span><span class='op'>)</span>
first_weighted <span class='op'>=</span> <span class='fu'><a href='first_isolate.html'>first_isolate</a></span><span class='op'>(</span>col_keyantimicrobials <span class='op'>=</span> <span class='st'>"keyab"</span><span class='op'>)</span>
<span class='op'>)</span>
<span class='co'># Check the difference, in this data set it results in a lot more isolates:</span>
<span class='co'># Check the difference, in this data set it results in more isolates:</span>
<span class='fu'><a href='https://rdrr.io/r/base/sum.html'>sum</a></span><span class='op'>(</span><span class='va'>my_patients</span><span class='op'>$</span><span class='va'>first_regular</span>, na.rm <span class='op'>=</span> <span class='cn'>TRUE</span><span class='op'>)</span>
<span class='fu'><a href='https://rdrr.io/r/base/sum.html'>sum</a></span><span class='op'>(</span><span class='va'>my_patients</span><span class='op'>$</span><span class='va'>first_weighted</span>, na.rm <span class='op'>=</span> <span class='cn'>TRUE</span><span class='op'>)</span>
<span class='op'>}</span>

View File

@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9008</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9007</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -82,7 +82,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="../index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9007</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -109,7 +109,7 @@
<loc>https://msberends.github.io/AMR//reference/join.html</loc>
</url>
<url>
<loc>https://msberends.github.io/AMR//reference/key_antibiotics.html</loc>
<loc>https://msberends.github.io/AMR//reference/key_antimicrobials.html</loc>
</url>
<url>
<loc>https://msberends.github.io/AMR//reference/kurtosis.html</loc>

View File

@ -81,7 +81,7 @@
</button>
<span class="navbar-brand">
<a class="navbar-link" href="index.html">AMR (for R)</a>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9009</span>
<span class="version label label-default" data-toggle="tooltip" data-placement="bottom" title="Latest development version">1.6.0.9010</span>
</span>
</div>

View File

@ -3,9 +3,47 @@
\name{AMR-deprecated}
\alias{AMR-deprecated}
\alias{p_symbol}
\alias{key_antibiotics}
\alias{key_antibiotics_equal}
\title{Deprecated Functions}
\usage{
p_symbol(p, emptychar = " ")
key_antibiotics(
x = NULL,
col_mo = NULL,
universal_1 = guess_ab_col(x, "amoxicillin"),
universal_2 = guess_ab_col(x, "amoxicillin/clavulanic acid"),
universal_3 = guess_ab_col(x, "cefuroxime"),
universal_4 = guess_ab_col(x, "piperacillin/tazobactam"),
universal_5 = guess_ab_col(x, "ciprofloxacin"),
universal_6 = guess_ab_col(x, "trimethoprim/sulfamethoxazole"),
GramPos_1 = guess_ab_col(x, "vancomycin"),
GramPos_2 = guess_ab_col(x, "teicoplanin"),
GramPos_3 = guess_ab_col(x, "tetracycline"),
GramPos_4 = guess_ab_col(x, "erythromycin"),
GramPos_5 = guess_ab_col(x, "oxacillin"),
GramPos_6 = guess_ab_col(x, "rifampin"),
GramNeg_1 = guess_ab_col(x, "gentamicin"),
GramNeg_2 = guess_ab_col(x, "tobramycin"),
GramNeg_3 = guess_ab_col(x, "colistin"),
GramNeg_4 = guess_ab_col(x, "cefotaxime"),
GramNeg_5 = guess_ab_col(x, "ceftazidime"),
GramNeg_6 = guess_ab_col(x, "meropenem"),
warnings = TRUE,
...
)
key_antibiotics_equal(
y,
z,
type = "keyantimicrobials",
ignore_I = TRUE,
points_threshold = 2,
info = FALSE,
na.rm = TRUE,
...
)
}
\description{
These functions are so-called '\link{Deprecated}'. They will be removed in a future release. Using the functions will give a warning with the name of the function it has been replaced by (if there is one).

View File

@ -19,12 +19,13 @@ first_isolate(
col_testcode = NULL,
col_specimen = NULL,
col_icu = NULL,
col_keyantibiotics = NULL,
col_keyantimicrobials = NULL,
episode_days = 365,
testcodes_exclude = NULL,
icu_exclude = FALSE,
specimen_group = NULL,
type = "keyantibiotics",
type = "points",
method = c("phenotype-based", "episode-based", "patient-based", "isolate-based"),
ignore_I = TRUE,
points_threshold = 2,
info = interactive(),
@ -38,6 +39,7 @@ filter_first_isolate(
col_date = NULL,
col_patient_id = NULL,
col_mo = NULL,
method = "episode-based",
...
)
@ -46,7 +48,7 @@ filter_first_weighted_isolate(
col_date = NULL,
col_patient_id = NULL,
col_mo = NULL,
col_keyantibiotics = NULL,
method = "phenotype-based",
...
)
}
@ -65,7 +67,7 @@ filter_first_weighted_isolate(
\item{col_icu}{column name of the logicals (\code{TRUE}/\code{FALSE}) whether a ward or department is an Intensive Care Unit (ICU)}
\item{col_keyantibiotics}{column name of the key antibiotics to determine first (weighted) isolates, see \code{\link[=key_antibiotics]{key_antibiotics()}}. Defaults to the first column that starts with 'key' followed by 'ab' or 'antibiotics' (case insensitive). Use \code{col_keyantibiotics = FALSE} to prevent this. Can also be the output of \code{\link[=key_antibiotics]{key_antibiotics()}}.}
\item{col_keyantimicrobials}{(only useful when \code{method = "phenotype-based"}) column name of the key antimicrobials to determine first (weighted) isolates, see \code{\link[=key_antimicrobials]{key_antimicrobials()}}. Defaults to the first column that starts with 'key' followed by 'ab' or 'antibiotics' or 'antimicrobials' (case insensitive). Use \code{col_keyantimicrobials = FALSE} to prevent this. Can also be the output of \code{\link[=key_antimicrobials]{key_antimicrobials()}}.}
\item{episode_days}{episode in days after which a genus/species combination will be determined as 'first isolate' again. The default of 365 days is based on the guideline by CLSI, see \emph{Source}.}
@ -75,11 +77,13 @@ filter_first_weighted_isolate(
\item{specimen_group}{value in the column set with \code{col_specimen} to filter on}
\item{type}{type to determine weighed isolates; can be \code{"keyantibiotics"} or \code{"points"}, see \emph{Details}}
\item{type}{type to determine weighed isolates; can be \code{"keyantimicrobials"} or \code{"points"}, see \emph{Details}}
\item{ignore_I}{logical to indicate whether antibiotic interpretations with \code{"I"} will be ignored when \code{type = "keyantibiotics"}, see \emph{Details}}
\item{method}{the algorithm to apply, either \code{"phenotype-based"}, \code{"episode-based"}, \code{"patient-based"} or \code{"isolate-based"} (can be abbreviated), see \emph{Details}}
\item{points_threshold}{points until the comparison of key antibiotics will lead to inclusion of an isolate when \code{type = "points"}, see \emph{Details}}
\item{ignore_I}{logical to indicate whether antibiotic interpretations with \code{"I"} will be ignored when \code{type = "keyantimicrobials"}, see \emph{Details}}
\item{points_threshold}{minimum number of points to require before differences in the antibiogram will lead to inclusion of an isolate when \code{type = "points"}, see \emph{Details}}
\item{info}{a \link{logical} to indicate info should be printed, defaults to \code{TRUE} only in interactive mode}
@ -87,7 +91,7 @@ filter_first_weighted_isolate(
\item{include_untested_rsi}{logical to indicate whether also rows without antibiotic results are still eligible for becoming a first isolate. Use \code{include_untested_rsi = FALSE} to always return \code{FALSE} for such rows. This checks the data set for columns of class \verb{<rsi>} and consequently requires transforming columns with antibiotic results using \code{\link[=as.rsi]{as.rsi()}} first.}
\item{...}{arguments passed on to \code{\link[=first_isolate]{first_isolate()}} when using \code{\link[=filter_first_isolate]{filter_first_isolate()}}, or arguments passed on to \code{\link[=key_antibiotics]{key_antibiotics()}} when using \code{\link[=filter_first_weighted_isolate]{filter_first_weighted_isolate()}}}
\item{...}{arguments passed on to \code{\link[=first_isolate]{first_isolate()}} when using \code{\link[=filter_first_isolate]{filter_first_isolate()}}, or arguments passed on to \code{\link[=key_antimicrobials]{key_antimicrobials()}} otherwise (such as \code{universal}, \code{gram_negative}, \code{gram_positive})}
}
\value{
A \code{\link{logical}} vector
@ -96,47 +100,77 @@ A \code{\link{logical}} vector
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 \code{\link[=is_new_episode]{is_new_episode()}} that also supports grouping with the \code{dplyr} package.
}
\details{
To conduct epidemiological analyses on antimicrobial resistance data, only so-called first isolates should be included to prevent overestimation and underestimation of antimicrobial resistance. Different algorithms can be used to do so, see below.
These functions are context-aware. This means that then the \code{x} argument can be left blank, see \emph{Examples}.
The \code{\link[=first_isolate]{first_isolate()}} function is a wrapper around the \code{\link[=is_new_episode]{is_new_episode()}} function, but more efficient for data sets containing microorganism codes or names.
All isolates with a microbial ID of \code{NA} will be excluded as first isolate.
\subsection{Why this is so Important}{
\subsection{Different algorithms}{
To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode \href{https://pubmed.ncbi.nlm.nih.gov/17304462/}{(Hindler \emph{et al.} 2007)}. If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all \emph{S. aureus} isolates would be overestimated, because you included this MRSA more than once. It would be \href{https://en.wikipedia.org/wiki/Selection_bias}{selection bias}.
According to Hindler \emph{et al.} (2007, \doi{10.1086/511864}), there are different algorithms to select first isolates with increasing reliability: isolate-based, patient-based, episode-based and phenotype-based. All algorithms select on a combination of the taxonomic genus and species (not subspecies).
All mentioned algorithms are covered in the \code{\link[=first_isolate]{first_isolate()}} function:\tabular{ll}{
\strong{Algorithm} \tab \strong{Function to apply} \cr
Isolate-based \tab \code{first_isolate(x, method = "isolate-based")} \cr
\emph{(= all isolates)} \tab \cr
\tab \cr
\tab \cr
Patient-based \tab \code{first_isolate(x, method = "patient-based")} \cr
\emph{(= first isolate per patient)} \tab \cr
\tab \cr
\tab \cr
Episode-based \tab \code{first_isolate(x, method = "episode-based")}, or: \cr
\emph{(= first isolate per episode)} \tab \cr
- 7-Day interval from initial isolate \tab - \code{first_isolate(x, method = "e", episode_days = 7)} \cr
- 30-Day interval from initial isolate \tab - \code{first_isolate(x, method = "e", episode_days = 30)} \cr
\tab \cr
\tab \cr
Phenotype-based \tab \code{first_isolate(x, method = "phenotype-based")}, or: \cr
\emph{(= first isolate per phenotype)} \tab \cr
- Major difference in any antimicrobial result \tab - \code{first_isolate(x, type = "points")} \cr
- Any difference in key antimicrobial results \tab - \code{first_isolate(x, type = "keyantimicrobials")} \cr
}
\subsection{\verb{filter_*()} Shortcuts}{
\subsection{Isolate-based}{
The functions \code{\link[=filter_first_isolate]{filter_first_isolate()}} and \code{\link[=filter_first_weighted_isolate]{filter_first_weighted_isolate()}} are helper functions to quickly filter on first isolates.
The function \code{\link[=filter_first_isolate]{filter_first_isolate()}} is essentially equal to either:\preformatted{ x[first_isolate(x, ...), ]
x \%>\% filter(first_isolate(...))
This algorithm does not require any selection, as all isolates should be included. It does, however, respect all arguments set in the \code{\link[=first_isolate]{first_isolate()}} function. For example, the default setting for \code{include_unknown} (\code{FALSE}) will omit selection of rows without a microbial ID.
}
The function \code{\link[=filter_first_weighted_isolate]{filter_first_weighted_isolate()}} is essentially equal to:\preformatted{ x \%>\%
mutate(keyab = key_antibiotics(.)) \%>\%
mutate(only_weighted_firsts = first_isolate(x,
col_keyantibiotics = "keyab", ...)) \%>\%
filter(only_weighted_firsts == TRUE) \%>\%
select(-only_weighted_firsts, -keyab)
}
}
}
\section{Key Antibiotics}{
\subsection{Patient-based}{
There are two ways to determine whether isolates can be included as first weighted isolates which will give generally the same results:
To include every genus-species combination per patient once, set the \code{episode_days} to \code{Inf}. Although often inappropriate, this algorithm makes sure that no duplicate isolates are selected from the same patient.
}
\subsection{Episode-based}{
To include every genus-species combination per patient episode once, set the \code{episode_days} to a sensible number of days. Depending on the type of analysis, this could be 14, 30, 60 or 365. Short episodes are common for analysing specific hospital or ward data, long episodes are common for analysing regional and national data.
This is the most common algorithm to correct for duplicate isolates. Patients are categorised into episodes based on their ID and dates (e.g., the date of specimen receipt or laboratory result). While this is a common algorithm, it does not take into account antimicrobial test results. This means that e.g. a methicillin-resistant \emph{Staphylococcus aureus} (MRSA) isolate cannot be differentiated from a wildtype \emph{Staphylococcus aureus} isolate.
}
\subsection{Phenotype-based}{
This is a more reliable algorithm, since it also \emph{weighs} the antibiogram (antimicrobial test results) yielding so-called 'first weighted isolates'. There are two different methods to weigh the antibiogram:
\enumerate{
\item Using \code{type = "keyantibiotics"} and argument \code{ignore_I}
Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With \code{ignore_I = FALSE}, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. Read more about this in the \code{\link[=key_antibiotics]{key_antibiotics()}} function.
\item Using \code{type = "points"} and argument \code{points_threshold}
A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds \code{points_threshold}, which defaults to \code{2}, an isolate will be (re)selected as a first weighted isolate.
}
This method weighs \emph{all} antimicrobial agents available in the data set. Any difference from I to S or R (or vice versa) counts as 0.5 points, a difference from S to R (or vice versa) counts as 1 point. When the sum of points exceeds \code{points_threshold}, which defaults to \code{2}, an isolate will be selected as a first weighted isolate.
All antimicrobials are internally selected using the \code{\link[=all_antimicrobials]{all_antimicrobials()}} function. The output of this function does not need to be passed to the \code{\link[=first_isolate]{first_isolate()}} function.
\item Using \code{type = "keyantimicrobials"} and argument \code{ignore_I}
This method only weighs specific antimicrobial agents, called \emph{key antimicrobials}. Any difference from S to R (or vice versa) in these key antimicrobials will select an isolate as a first weighted isolate. With \code{ignore_I = FALSE}, also differences from I to S or R (or vice versa) will lead to this.
Key antimicrobials are internally selected using the \code{\link[=key_antimicrobials]{key_antimicrobials()}} function, but can also be added manually as a variable to the data and set in the \code{col_keyantimicrobials} argument. Another option is to pass the output of the \code{\link[=key_antimicrobials]{key_antimicrobials()}} function directly to the \code{col_keyantimicrobials} argument.
}
The default algorithm is phenotype-based (using \code{type = "points"}) and episode-based (using \code{episode_days = 365}). This makes sure that every genus-species combination is selected per patient once per year, while taking into account all antimicrobial test results.
}
}
}
\section{Stable Lifecycle}{
\if{html}{\figure{lifecycle_stable.svg}{options: style=margin-bottom:5px} \cr}
@ -155,7 +189,6 @@ On our website \url{https://msberends.github.io/AMR/} you can find \href{https:/
# See ?example_isolates.
example_isolates[first_isolate(example_isolates), ]
\donttest{
# faster way, only works in R 3.2 and later:
example_isolates[first_isolate(), ]
@ -193,11 +226,11 @@ if (require("dplyr")) {
# Have a look at A and B.
# B is more reliable because every isolate is counted only once.
# Gentamicin resistance in hospital D appears to be 3.7\% higher than
# Gentamicin resistance in hospital D appears to be 4.2\% higher than
# when you (erroneously) would have used all isolates for analysis.
}
}
}
\seealso{
\code{\link[=key_antibiotics]{key_antibiotics()}}
\code{\link[=key_antimicrobials]{key_antimicrobials()}}
}

View File

@ -1,176 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/key_antibiotics.R
\name{key_antibiotics}
\alias{key_antibiotics}
\alias{key_antibiotics_equal}
\title{Key Antibiotics for First (Weighted) Isolates}
\usage{
key_antibiotics(
x = NULL,
col_mo = NULL,
universal_1 = guess_ab_col(x, "amoxicillin"),
universal_2 = guess_ab_col(x, "amoxicillin/clavulanic acid"),
universal_3 = guess_ab_col(x, "cefuroxime"),
universal_4 = guess_ab_col(x, "piperacillin/tazobactam"),
universal_5 = guess_ab_col(x, "ciprofloxacin"),
universal_6 = guess_ab_col(x, "trimethoprim/sulfamethoxazole"),
GramPos_1 = guess_ab_col(x, "vancomycin"),
GramPos_2 = guess_ab_col(x, "teicoplanin"),
GramPos_3 = guess_ab_col(x, "tetracycline"),
GramPos_4 = guess_ab_col(x, "erythromycin"),
GramPos_5 = guess_ab_col(x, "oxacillin"),
GramPos_6 = guess_ab_col(x, "rifampin"),
GramNeg_1 = guess_ab_col(x, "gentamicin"),
GramNeg_2 = guess_ab_col(x, "tobramycin"),
GramNeg_3 = guess_ab_col(x, "colistin"),
GramNeg_4 = guess_ab_col(x, "cefotaxime"),
GramNeg_5 = guess_ab_col(x, "ceftazidime"),
GramNeg_6 = guess_ab_col(x, "meropenem"),
warnings = TRUE,
...
)
key_antibiotics_equal(
y,
z,
type = c("keyantibiotics", "points"),
ignore_I = TRUE,
points_threshold = 2,
info = FALSE,
na.rm = TRUE,
...
)
}
\arguments{
\item{x}{a \link{data.frame} with antibiotics columns, like \code{AMX} or \code{amox}. Can be left blank to determine automatically}
\item{col_mo}{column name of the IDs of the microorganisms (see \code{\link[=as.mo]{as.mo()}}), defaults to the first column of class \code{\link{mo}}. Values will be coerced using \code{\link[=as.mo]{as.mo()}}.}
\item{universal_1, universal_2, universal_3, universal_4, universal_5, universal_6}{column names of \strong{broad-spectrum} antibiotics, case-insensitive. See details for which antibiotics will be used at default (which are guessed with \code{\link[=guess_ab_col]{guess_ab_col()}}).}
\item{GramPos_1, GramPos_2, GramPos_3, GramPos_4, GramPos_5, GramPos_6}{column names of antibiotics for \strong{Gram-positives}, case-insensitive. See details for which antibiotics will be used at default (which are guessed with \code{\link[=guess_ab_col]{guess_ab_col()}}).}
\item{GramNeg_1, GramNeg_2, GramNeg_3, GramNeg_4, GramNeg_5, GramNeg_6}{column names of antibiotics for \strong{Gram-negatives}, case-insensitive. See details for which antibiotics will be used at default (which are guessed with \code{\link[=guess_ab_col]{guess_ab_col()}}).}
\item{warnings}{give a warning about missing antibiotic columns (they will be ignored)}
\item{...}{other arguments passed on to functions}
\item{y, z}{character vectors to compare}
\item{type}{type to determine weighed isolates; can be \code{"keyantibiotics"} or \code{"points"}, see \emph{Details}}
\item{ignore_I}{logical to indicate whether antibiotic interpretations with \code{"I"} will be ignored when \code{type = "keyantibiotics"}, see \emph{Details}}
\item{points_threshold}{points until the comparison of key antibiotics will lead to inclusion of an isolate when \code{type = "points"}, see \emph{Details}}
\item{info}{unused - previously used to indicate whether a progress bar should print}
\item{na.rm}{a \link{logical} to indicate whether comparison with \code{NA} should return \code{FALSE} (defaults to \code{TRUE} for backwards compatibility)}
}
\description{
These function can be used to determine first isolates (see \code{\link[=first_isolate]{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.
}
\details{
The \code{\link[=key_antibiotics]{key_antibiotics()}} function is context-aware. This means that then the \code{x} argument can be left blank, see \emph{Examples}.
The function \code{\link[=key_antibiotics]{key_antibiotics()}} returns a character vector with 12 antibiotic results for every isolate. These isolates can then be compared using \code{\link[=key_antibiotics_equal]{key_antibiotics_equal()}}, to check if two isolates have generally the same antibiogram. Missing and invalid values are replaced with a dot (\code{"."}) by \code{\link[=key_antibiotics]{key_antibiotics()}} and ignored by \code{\link[=key_antibiotics_equal]{key_antibiotics_equal()}}.
The \code{\link[=first_isolate]{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 \emph{S. aureus} (MSSA) is found within the same patient episode. Without key antibiotic comparison it would not. See \code{\link[=first_isolate]{first_isolate()}} for more info.
At default, the antibiotics that are used for \strong{Gram-positive bacteria} are:
\itemize{
\item Amoxicillin
\item Amoxicillin/clavulanic acid
\item Cefuroxime
\item Piperacillin/tazobactam
\item Ciprofloxacin
\item Trimethoprim/sulfamethoxazole
\item Vancomycin
\item Teicoplanin
\item Tetracycline
\item Erythromycin
\item Oxacillin
\item Rifampin
}
At default the antibiotics that are used for \strong{Gram-negative bacteria} are:
\itemize{
\item Amoxicillin
\item Amoxicillin/clavulanic acid
\item Cefuroxime
\item Piperacillin/tazobactam
\item Ciprofloxacin
\item Trimethoprim/sulfamethoxazole
\item Gentamicin
\item Tobramycin
\item Colistin
\item Cefotaxime
\item Ceftazidime
\item Meropenem
}
The function \code{\link[=key_antibiotics_equal]{key_antibiotics_equal()}} checks the characters returned by \code{\link[=key_antibiotics]{key_antibiotics()}} for equality, and returns a \code{\link{logical}} vector.
}
\section{Stable Lifecycle}{
\if{html}{\figure{lifecycle_stable.svg}{options: style=margin-bottom:5px} \cr}
The \link[=lifecycle]{lifecycle} of this function is \strong{stable}. In a stable function, major changes are unlikely. This means that the unlying code will generally evolve by adding new arguments; removing arguments or changing the meaning of existing arguments will be avoided.
If the unlying code needs breaking changes, they will occur gradually. For example, a argument will be deprecated and first continue to work, but will emit an message informing you of the change. Next, typically after at least one newly released version on CRAN, the message will be transformed to an error.
}
\section{Key Antibiotics}{
There are two ways to determine whether isolates can be included as first weighted isolates which will give generally the same results:
\enumerate{
\item Using \code{type = "keyantibiotics"} and argument \code{ignore_I}
Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With \code{ignore_I = FALSE}, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. Read more about this in the \code{\link[=key_antibiotics]{key_antibiotics()}} function.
\item Using \code{type = "points"} and argument \code{points_threshold}
A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds \code{points_threshold}, which defaults to \code{2}, an isolate will be (re)selected as a first weighted isolate.
}
}
\section{Read more on Our Website!}{
On our website \url{https://msberends.github.io/AMR/} you can find \href{https://msberends.github.io/AMR/articles/AMR.html}{a comprehensive tutorial} about how to conduct AMR data analysis, the \href{https://msberends.github.io/AMR/reference/}{complete documentation of all functions} and \href{https://msberends.github.io/AMR/articles/WHONET.html}{an example analysis using WHONET data}. As we would like to better understand the backgrounds and needs of our users, please \href{https://msberends.github.io/AMR/survey.html}{participate in our survey}!
}
\examples{
# `example_isolates` is a data set available in the AMR package.
# See ?example_isolates.
# output of the `key_antibiotics()` function could be like this:
strainA <- "SSSRR.S.R..S"
strainB <- "SSSIRSSSRSSS"
# 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 character differs
\donttest{
if (require("dplyr")) {
# set key antibiotics to a new variable
my_patients <- example_isolates \%>\%
mutate(keyab = key_antibiotics()) \%>\% # no need to define `x`
mutate(
# now calculate first isolates
first_regular = first_isolate(col_keyantibiotics = FALSE),
# and first WEIGHTED isolates
first_weighted = first_isolate(col_keyantibiotics = "keyab")
)
# 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)
}
}
}
\seealso{
\code{\link[=first_isolate]{first_isolate()}}
}

159
man/key_antimicrobials.Rd Normal file
View File

@ -0,0 +1,159 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/key_antimicrobials.R
\name{key_antimicrobials}
\alias{key_antimicrobials}
\alias{all_antimicrobials}
\alias{antimicrobials_equal}
\title{(Key) Antimicrobials for First Weighted Isolates}
\usage{
key_antimicrobials(
x = NULL,
col_mo = NULL,
universal = c("ampicillin", "amoxicillin/clavulanic acid", "cefuroxime",
"piperacillin/tazobactam", "ciprofloxacin", "trimethoprim/sulfamethoxazole"),
gram_negative = c("gentamicin", "tobramycin", "colistin", "cefotaxime",
"ceftazidime", "meropenem"),
gram_positive = c("vancomycin", "teicoplanin", "tetracycline", "erythromycin",
"oxacillin", "rifampin"),
antifungal = c("anidulafungin", "caspofungin", "fluconazole", "miconazole",
"nystatin", "voriconazole"),
only_rsi_columns = FALSE,
...
)
all_antimicrobials(x = NULL, only_rsi_columns = FALSE, ...)
antimicrobials_equal(
y,
z,
type = c("points", "keyantimicrobials"),
ignore_I = TRUE,
points_threshold = 2,
info = FALSE,
...
)
}
\arguments{
\item{x}{a \link{data.frame} with antibiotics columns, like \code{AMX} or \code{amox}. Can be left blank to determine automatically}
\item{col_mo}{column name of the IDs of the microorganisms (see \code{\link[=as.mo]{as.mo()}}), defaults to the first column of class \code{\link{mo}}. Values will be coerced using \code{\link[=as.mo]{as.mo()}}.}
\item{universal}{names of \strong{broad-spectrum} antimicrobial agents, case-insensitive. Set to \code{NULL} to ignore. See \emph{Details} for the default agents.}
\item{gram_negative}{names of antibiotic agents for \strong{Gram-positives}, case-insensitive. Set to \code{NULL} to ignore. See \emph{Details} for the default agents.}
\item{gram_positive}{names of antibiotic agents for \strong{Gram-negatives}, case-insensitive. Set to \code{NULL} to ignore. See \emph{Details} for the default agents.}
\item{antifungal}{names of antifungal agents for \strong{fungi}, case-insensitive. Set to \code{NULL} to ignore. See \emph{Details} for the default agents.}
\item{...}{ignored, allows for future extensions}
\item{y, z}{character vectors to compare}
\item{type}{type to determine weighed isolates; can be \code{"keyantimicrobials"} or \code{"points"}, see \emph{Details}}
\item{ignore_I}{logical to indicate whether antibiotic interpretations with \code{"I"} will be ignored when \code{type = "keyantimicrobials"}, see \emph{Details}}
\item{points_threshold}{minimum number of points to require before differences in the antibiogram will lead to inclusion of an isolate when \code{type = "points"}, see \emph{Details}}
\item{info}{unused - previously used to indicate whether a progress bar should print}
}
\description{
These functions can be used to determine first weighted isolates by considering the phenotype for isolate selection (see \code{\link[=first_isolate]{first_isolate()}}). Using a phenotype-based method to determine first isolates is more reliable than methods that disregard phenotypes.
}
\details{
The \code{\link[=key_antimicrobials]{key_antimicrobials()}} and \code{\link[=all_antimicrobials]{all_antimicrobials()}} functions are context-aware. This means that then the \code{x} argument can be left blank, see \emph{Examples}.
The function \code{\link[=key_antimicrobials]{key_antimicrobials()}} returns a character vector with 12 antimicrobial results for every isolate. The function \code{\link[=all_antimicrobials]{all_antimicrobials()}} returns a character vector with all antimicrobial results for every isolate. These vectors can then be compared using \code{\link[=antimicrobials_equal]{antimicrobials_equal()}}, to check if two isolates have generally the same antibiogram. Missing and invalid values are replaced with a dot (\code{"."}) by \code{\link[=key_antimicrobials]{key_antimicrobials()}} and ignored by \code{\link[=antimicrobials_equal]{antimicrobials_equal()}}.
Please see the \code{\link[=first_isolate]{first_isolate()}} function how these important functions enable the 'phenotype-based' method for determination of first isolates.
The default antimicrobial agents used for \strong{all rows} (set in \code{universal}) are:
\itemize{
\item Ampicillin
\item Amoxicillin/clavulanic acid
\item Cefuroxime
\item Ciprofloxacin
\item Piperacillin/tazobactam
\item Trimethoprim/sulfamethoxazole
}
The default antimicrobial agents used for \strong{Gram-negative bacteria} (set in \code{gram_negative}) are:
\itemize{
\item Cefotaxime
\item Ceftazidime
\item Colistin
\item Gentamicin
\item Meropenem
\item Tobramycin
}
The default antimicrobial agents used for \strong{Gram-positive bacteria} (set in \code{gram_positive}) are:
\itemize{
\item Erythromycin
\item Oxacillin
\item Rifampin
\item Teicoplanin
\item Tetracycline
\item Vancomycin
}
The default antimicrobial agents used for \strong{fungi} (set in \code{antifungal}) are:
\itemize{
\item Anidulafungin
\item Caspofungin
\item Fluconazole
\item Miconazole
\item Nystatin
\item Voriconazole
}
}
\section{Stable Lifecycle}{
\if{html}{\figure{lifecycle_stable.svg}{options: style=margin-bottom:5px} \cr}
The \link[=lifecycle]{lifecycle} of this function is \strong{stable}. In a stable function, major changes are unlikely. This means that the unlying code will generally evolve by adding new arguments; removing arguments or changing the meaning of existing arguments will be avoided.
If the unlying code needs breaking changes, they will occur gradually. For example, a argument will be deprecated and first continue to work, but will emit an message informing you of the change. Next, typically after at least one newly released version on CRAN, the message will be transformed to an error.
}
\section{Read more on Our Website!}{
On our website \url{https://msberends.github.io/AMR/} you can find \href{https://msberends.github.io/AMR/articles/AMR.html}{a comprehensive tutorial} about how to conduct AMR data analysis, the \href{https://msberends.github.io/AMR/reference/}{complete documentation of all functions} and \href{https://msberends.github.io/AMR/articles/WHONET.html}{an example analysis using WHONET data}. As we would like to better understand the backgrounds and needs of our users, please \href{https://msberends.github.io/AMR/survey.html}{participate in our survey}!
}
\examples{
# `example_isolates` is a data set available in the AMR package.
# See ?example_isolates.
# output of the `key_antimicrobials()` function could be like this:
strainA <- "SSSRR.S.R..S"
strainB <- "SSSIRSSSRSSS"
# those strings can be compared with:
antimicrobials_equal(strainA, strainB, type = "keyantimicrobials")
# TRUE, because I is ignored (as well as missing values)
antimicrobials_equal(strainA, strainB, type = "keyantimicrobials", ignore_I = FALSE)
# 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_antimicrobials(antifungal = NULL)) \%>\% # no need to define `x`
mutate(
# now calculate first isolates
first_regular = first_isolate(col_keyantimicrobials = FALSE),
# and first WEIGHTED isolates
first_weighted = first_isolate(col_keyantimicrobials = "keyab")
)
# Check the difference, in this data set it results in more isolates:
sum(my_patients$first_regular, na.rm = TRUE)
sum(my_patients$first_weighted, na.rm = TRUE)
}
}
}
\seealso{
\code{\link[=first_isolate]{first_isolate()}}
}

View File

@ -28,58 +28,29 @@ context("first_isolate.R")
test_that("first isolates work", {
skip_on_cran()
# first isolates
expect_equal(
sum(
first_isolate(x = example_isolates,
col_date = "date",
col_patient_id = "patient_id",
col_mo = "mo",
info = TRUE),
na.rm = TRUE),
1300)
# first weighted isolates
ex_iso_with_keyab <- example_isolates
ex_iso_with_keyab$keyab <- key_antibiotics(example_isolates, warnings = FALSE)
expect_equal(
suppressWarnings(
sum(
first_isolate(x = ex_iso_with_keyab,
# let syntax determine arguments automatically
type = "keyantibiotics",
info = TRUE),
na.rm = TRUE)),
1398)
# when not ignoring I
expect_equal(
suppressWarnings(
sum(
first_isolate(x = ex_iso_with_keyab,
col_date = "date",
col_patient_id = "patient_id",
col_mo = "mo",
col_keyantibiotics = "keyab",
ignore_I = FALSE,
type = "keyantibiotics",
info = TRUE),
na.rm = TRUE)),
1421)
# when using points
expect_equal(
suppressWarnings(
sum(
first_isolate(x = ex_iso_with_keyab,
col_date = "date",
col_patient_id = "patient_id",
col_mo = "mo",
col_keyantibiotics = "keyab",
type = "points",
info = TRUE),
na.rm = TRUE)),
1348)
# all four methods
expect_equal(sum(first_isolate(x = example_isolates, method = "isolate-based", info = TRUE), na.rm = TRUE),
1984)
expect_equal(sum(first_isolate(x = example_isolates, method = "patient-based", info = TRUE), na.rm = TRUE),
1265)
expect_equal(sum(first_isolate(x = example_isolates, method = "episode-based", info = TRUE), na.rm = TRUE),
1300)
expect_equal(sum(first_isolate(x = example_isolates, method = "phenotype-based", info = TRUE), na.rm = TRUE),
1379)
# Phenotype-based, using key antimicrobials
expect_equal(sum(first_isolate(x = example_isolates,
method = "phenotype-based",
type = "keyantimicrobials",
antifungal = NULL, info = TRUE), na.rm = TRUE),
1395)
expect_equal(sum(first_isolate(x = example_isolates,
method = "phenotype-based",
type = "keyantimicrobials",
antifungal = NULL, info = TRUE, ignore_I = FALSE), na.rm = TRUE),
1418)
# first non-ICU isolates
expect_equal(
sum(
@ -91,7 +62,7 @@ test_that("first isolates work", {
info = TRUE,
icu_exclude = TRUE),
na.rm = TRUE),
881)
941)
# set 1500 random observations to be of specimen type 'Urine'
random_rows <- sample(x = 1:2000, size = 1500, replace = FALSE)
@ -157,11 +128,13 @@ test_that("first isolates work", {
mutate(mo = as.character(mo)) %>%
first_isolate(col_date = "date",
col_mo = "mo",
col_patient_id = "patient_id"),
col_patient_id = "patient_id",
info = FALSE),
example_isolates %>%
first_isolate(col_date = "date",
col_mo = "mo",
col_patient_id = "patient_id"))
col_patient_id = "patient_id",
info = FALSE))
# support for WHONET
expect_message(example_isolates %>%
@ -182,31 +155,29 @@ test_that("first isolates work", {
col_mo = "mo",
info = TRUE),
na.rm = TRUE),
1305)
1382)
# unknown MOs
test_unknown <- example_isolates
test_unknown$mo <- ifelse(test_unknown$mo == "B_ESCHR_COLI", "UNKNOWN", test_unknown$mo)
expect_equal(sum(first_isolate(test_unknown, include_unknown = FALSE)),
1045)
1108)
expect_equal(sum(first_isolate(test_unknown, include_unknown = TRUE)),
1528)
1591)
test_unknown$mo <- ifelse(test_unknown$mo == "UNKNOWN", NA, test_unknown$mo)
expect_equal(sum(first_isolate(test_unknown)),
1045)
1108)
# empty rsi results
expect_equal(sum(first_isolate(example_isolates, include_untested_rsi = FALSE)),
1287)
1366)
# shortcuts
expect_identical(filter_first_isolate(example_isolates),
subset(example_isolates, first_isolate(example_isolates)))
ex <- example_isolates
ex$keyab <- key_antibiotics(ex)
subset(example_isolates, first_isolate(example_isolates, method = "episode-based")))
expect_identical(filter_first_weighted_isolate(example_isolates),
subset(example_isolates, first_isolate(ex)))
subset(example_isolates, first_isolate(example_isolates, method = "phenotype-based")))
# notice that all mo's are distinct, so all are TRUE
expect_true(all(example_isolates %pm>%

View File

@ -23,19 +23,20 @@
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
context("key_antibiotics.R")
context("key_antimcrobials.R")
test_that("keyantibiotics work", {
test_that("key_antimcrobials work", {
skip_on_cran()
expect_equal(length(key_antibiotics(example_isolates, warnings = FALSE)), nrow(example_isolates))
expect_false(all(is.na(key_antibiotics(example_isolates))))
expect_true(key_antibiotics_equal("SSS", "SSS"))
expect_false(key_antibiotics_equal("SSS", "SRS"))
expect_true(key_antibiotics_equal("SSS", "SIS", ignore_I = TRUE))
expect_false(key_antibiotics_equal("SSS", "SIS", ignore_I = FALSE))
expect_true(key_antibiotics_equal(".SS", "SI.", ignore_I = TRUE))
expect_false(key_antibiotics_equal(".SS", "SI.", ignore_I = FALSE))
expect_equal(length(key_antimicrobials(example_isolates, antifungal = NULL)), nrow(example_isolates))
expect_false(all(is.na(key_antimicrobials(example_isolates, antifungal = NULL))))
expect_true(antimicrobials_equal("SSS", "SSS"))
expect_false(antimicrobials_equal("SSS", "SRS", type = "keyantimicrobials"))
expect_true(antimicrobials_equal("SSS", "SRS", type = "points"))
expect_true(antimicrobials_equal("SSS", "SIS", ignore_I = TRUE, type = "keyantimicrobials"))
expect_false(antimicrobials_equal("SSS", "SIS", ignore_I = FALSE, type = "keyantimicrobials"))
expect_true(antimicrobials_equal(".SS", "SI.", ignore_I = TRUE, type = "keyantimicrobials"))
expect_false(antimicrobials_equal(".SS", "SI.", ignore_I = FALSE, type = "keyantimicrobials"))
library(dplyr, warn.conflicts = FALSE)
expect_warning(key_antibiotics(example_isolates %>% slice(rep(1, 10))))
expect_warning(key_antimicrobials(example_isolates %>% slice(rep(1, 10))))
})