From 2acdb1981cb0c9346b5ef68c06b8ebe78073c061 Mon Sep 17 00:00:00 2001 From: "Matthijs S. Berends" Date: Sat, 25 Aug 2018 22:01:14 +0200 Subject: [PATCH] atc and bactid functions, readme update --- DESCRIPTION | 2 +- NAMESPACE | 24 +- NEWS.md | 2 + R/abname.R | 32 +-- R/atc.R | 263 ++++++++++++------ R/bactid.R | 76 +++++ R/data.R | 21 +- R/eucast.R | 35 --- R/globals.R | 2 +- R/{classes.R => mic.R} | 180 ------------ R/portion.R | 45 +++ R/rsi.R | 206 +++++++++++--- README.md | 46 +-- data/antibiotics.rda | Bin 12654 -> 12652 bytes man/abname.Rd | 12 +- man/antibiotics.Rd | 2 +- man/{guess_atc.Rd => as.atc.Rd} | 30 +- man/as.mic.Rd | 2 +- man/as.rsi.Rd | 2 +- man/atc.property.Rd | 27 ++ man/bactid.property.Rd | 42 +++ man/mo_property.Rd | 19 -- man/rsi.Rd | 2 +- tests/testthat/test-abname.R | 2 +- tests/testthat/test-atc.R | 15 +- tests/testthat/test-bactid.R | 13 + tests/testthat/test-eucast.R | 5 - tests/testthat/{test-classes.R => test-mic.R} | 23 +- tests/testthat/test-rsi.R | 22 ++ vignettes/AMR.Rmd | 58 ++++ 30 files changed, 761 insertions(+), 449 deletions(-) rename R/{classes.R => mic.R} (63%) rename man/{guess_atc.Rd => as.atc.Rd} (54%) mode change 100755 => 100644 create mode 100644 man/atc.property.Rd create mode 100644 man/bactid.property.Rd delete mode 100755 man/mo_property.Rd rename tests/testthat/{test-classes.R => test-mic.R} (52%) create mode 100644 tests/testthat/test-rsi.R create mode 100755 vignettes/AMR.Rmd diff --git a/DESCRIPTION b/DESCRIPTION index 389458ea..14bc05e8 100755 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: AMR -Version: 0.3.0.9003 +Version: 0.3.0.9004 Date: 2018-08-23 Title: Antimicrobial Resistance Analysis Authors@R: c( diff --git a/NAMESPACE b/NAMESPACE index 32499f4a..d1f1a847 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +S3method(as.data.frame,atc) S3method(as.data.frame,bactid) S3method(as.data.frame,frequency_tbl) S3method(as.double,mic) @@ -17,10 +18,12 @@ S3method(kurtosis,matrix) S3method(plot,frequency_tbl) S3method(plot,mic) S3method(plot,rsi) +S3method(print,atc) S3method(print,bactid) S3method(print,frequency_tbl) S3method(print,mic) S3method(print,rsi) +S3method(pull,atc) S3method(pull,bactid) S3method(skewness,data.frame) S3method(skewness,default) @@ -35,12 +38,28 @@ export(MDRO) export(MRGN) export(abname) export(anti_join_microorganisms) +export(as.atc) export(as.bactid) export(as.mic) export(as.rsi) +export(atc.certe) +export(atc.official) +export(atc.official_nl) +export(atc.trivial_nl) +export(atc.umcg) export(atc_ddd) export(atc_groups) export(atc_property) +export(bactid.aerobic) +export(bactid.family) +export(bactid.fullname) +export(bactid.genus) +export(bactid.gramstain) +export(bactid.gramstain_nl) +export(bactid.species) +export(bactid.subspecies) +export(bactid.type) +export(bactid.type_nl) export(clipboard_export) export(clipboard_import) export(count_I) @@ -61,6 +80,7 @@ export(guess_atc) export(guess_bactid) export(inner_join_microorganisms) export(interpretive_reading) +export(is.atc) export(is.bactid) export(is.mic) export(is.rsi) @@ -70,7 +90,6 @@ export(key_antibiotics_equal) export(kurtosis) export(left_join_microorganisms) export(like) -export(mo_property) export(n_rsi) export(p.symbol) export(portion_I) @@ -89,6 +108,7 @@ export(semi_join_microorganisms) export(skewness) export(theme_rsi) export(top_freq) +exportMethods(as.data.frame.atc) exportMethods(as.data.frame.bactid) exportMethods(as.data.frame.frequency_tbl) exportMethods(as.double.mic) @@ -107,10 +127,12 @@ exportMethods(kurtosis.matrix) exportMethods(plot.frequency_tbl) exportMethods(plot.mic) exportMethods(plot.rsi) +exportMethods(print.atc) exportMethods(print.bactid) exportMethods(print.frequency_tbl) exportMethods(print.mic) exportMethods(print.rsi) +exportMethods(pull.atc) exportMethods(pull.bactid) exportMethods(skewness) exportMethods(skewness.data.frame) diff --git a/NEWS.md b/NEWS.md index 7aef6641..4f72693e 100755 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,8 @@ * Functions `count_R`, `count_IR`, `count_I`, `count_SI` and `count_S` to selectively count resistant or susceptible isolates * New function `count_df` to get all counts of S, I and R of a data set with antibiotic columns, with support for grouped variables * Function `is.rsi.eligible` to check for columns that have valid antimicrobial results, but do not have the `rsi` class yet. Transform the columns of your raw data with: `data %>% mutate_if(is.rsi.eligible, as.rsi)` +* Functions `as.atc` and `is.atc` to transform/look up antibiotic ATC codes as defined by the WHO. The existing function `guess_atc` is now an alias of `as.atc`. +* Function `mo_property` removed in favour of functions `bactid.family`, `bactid.genus`, `bactid.species`, `bactid.subspecies`, `bactid.fullname`, `bactid.type`, `bactid.gramstain`, `bactid.aerobic` to get a property of a microorganism based on their 'bactid'. #### Changed * Removed function `ratio` diff --git a/R/abname.R b/R/abname.R index 4cc26125..2086b035 100644 --- a/R/abname.R +++ b/R/abname.R @@ -18,9 +18,9 @@ #' Name of an antibiotic #' -#' Convert antibiotic codes (from a laboratory information system like MOLIS or GLIMS) to a (trivial) antibiotic name or ATC code, or vice versa. This uses the data from \code{\link{antibiotics}}. +#' Convert antibiotic codes to a (trivial) antibiotic name or ATC code, or vice versa. This uses the data from \code{\link{antibiotics}}. #' @param abcode a code or name, like \code{"AMOX"}, \code{"AMCL"} or \code{"J01CA04"} -#' @param from,to type to transform from and to. See \code{\link{antibiotics}} for its column names. WIth \code{from = "guess"} the from will be guessed from \code{"atc"}, \code{"molis"} and \code{"umcg"}. When using \code{to = "atc"}, the ATC code will be searched using \code{\link{guess_atc}}. +#' @param from,to type to transform from and to. See \code{\link{antibiotics}} for its column names. WIth \code{from = "guess"} the from will be guessed from \code{"atc"}, \code{"certe"} and \code{"umcg"}. When using \code{to = "atc"}, the ATC code will be searched using \code{\link{as.atc}}. #' @param textbetween text to put between multiple returned texts #' @param tolower return output as lower case with function \code{\link{tolower}}. #' @keywords ab antibiotics @@ -29,7 +29,7 @@ #' @importFrom dplyr %>% pull #' @examples #' abname("AMCL") -#' # "amoxicillin and enzyme inhibitor" +#' # "Amoxicillin and beta-lactamase inhibitor" #' #' # It is quite flexible at default (having `from = "guess"`) #' abname(c("amox", "J01CA04", "Trimox", "dispermox", "Amoxil")) @@ -52,8 +52,12 @@ #' # specific codes for University Medical Center Groningen (UMCG): #' abname("J01CR02", from = "atc", to = "umcg") #' # "AMCL" +#' +#' # specific codes for Certe: +#' abname("J01CR02", from = "atc", to = "certe") +#' # "amcl" abname <- function(abcode, - from = c("guess", "atc", "molis", "umcg"), + from = c("guess", "atc", "certe", "umcg"), to = 'official', textbetween = ' + ', tolower = FALSE) { @@ -63,24 +67,12 @@ abname <- function(abcode, } if (to == "atc") { - return(guess_atc(abcode)) + return(as.character(as.atc(abcode))) } - #antibiotics <- AMR::antibiotics abx <- AMR::antibiotics from <- from[1] - # if (from == "guess") { - # for (i in 1:3) { - # if (abcode[1] %in% (antibiotics %>% pull(i))) { - # from <- colnames(antibiotics)[i] - # } - # } - # if (from == "guess") { - # from <- "umcg" - # } - # } - colnames(abx) <- colnames(abx) %>% tolower() from <- from %>% tolower() to <- to %>% tolower() @@ -112,9 +104,9 @@ abname <- function(abcode, next } } - if (from %in% c("molis", "guess")) { - if (abcode[i] %in% abx$molis) { - abcode[i] <- abx[which(abx$molis == abcode[i]),] %>% pull(to) + if (from %in% c("certe", "guess")) { + if (abcode[i] %in% abx$certe) { + abcode[i] <- abx[which(abx$certe == abcode[i]),] %>% pull(to) next } } diff --git a/R/atc.R b/R/atc.R index bd440158..1caa3747 100755 --- a/R/atc.R +++ b/R/atc.R @@ -16,6 +16,185 @@ # GNU General Public License for more details. # # ==================================================================== # + +#' Find ATC code based on antibiotic property +#' +#' Use this function to determine the ATC code of one or more antibiotics. The dataset \code{\link{antibiotics}} will be searched for abbreviations, official names and trade names. +#' @param x character vector to determine \code{ATC} code +#' @rdname as.atc +#' @aliases atc +#' @keywords atc +#' @export +#' @importFrom dplyr %>% filter slice pull +#' @details In the ATC classification system, the active substances are classified in a hierarchy with five different levels. The system has fourteen main anatomical/pharmacological groups or 1st levels. Each ATC main group is divided into 2nd levels which could be either pharmacological or therapeutic groups. The 3rd and 4th levels are chemical, pharmacological or therapeutic subgroups and the 5th level is the chemical substance. The 2nd, 3rd and 4th levels are often used to identify pharmacological subgroups when that is considered more appropriate than therapeutic or chemical subgroups. +#' Source: \url{https://www.whocc.no/atc/structure_and_principles/} +#' @return Character (vector) with class \code{"act"}. Unknown values will return \code{NA}. +#' @seealso \code{\link{antibiotics}} for the dataframe that is being used to determine ATC's. +#' @examples +#' # These examples all return "J01FA01", the ATC code of Erythromycin: +#' as.atc("J01FA01") +#' as.atc("Erythromycin") +#' as.atc("eryt") +#' as.atc("ERYT") +#' as.atc("ERY") +#' as.atc("Erythrocin") # Trade name +#' as.atc("Eryzole") # Trade name +#' as.atc("Pediamycin") # Trade name +as.atc <- function(x) { + + x.new <- rep(NA_character_, length(x)) + x.bak <- x + x <- unique(x[!is.na(x)]) + failures <- character(0) + + for (i in 1:length(x)) { + fail <- TRUE + + # first try atc + found <- AMR::antibiotics[which(AMR::antibiotics$atc == x[i]),]$atc + if (length(found) > 0) { + fail <- FALSE + x.new[is.na(x.new) & x.bak == x[i]] <- found[1L] + } + + # try abbreviation of certe and glims + found <- AMR::antibiotics[which(tolower(AMR::antibiotics$certe) == tolower(x[i])),]$atc + if (length(found) > 0) { + fail <- FALSE + x.new[is.na(x.new) & x.bak == x[i]] <- found[1L] + } + found <- AMR::antibiotics[which(tolower(AMR::antibiotics$umcg) == tolower(x[i])),]$atc + if (length(found) > 0) { + fail <- FALSE + x.new[is.na(x.new) & x.bak == x[i]] <- found[1L] + } + + # try exact official name + found <- AMR::antibiotics[which(tolower(AMR::antibiotics$official) == tolower(x[i])),]$atc + if (length(found) > 0) { + fail <- FALSE + x.new[is.na(x.new) & x.bak == x[i]] <- found[1L] + } + + # try trade name + found <- AMR::antibiotics[which(paste0("(", AMR::antibiotics$trade_name, ")") %like% x[i]),]$atc + if (length(found) > 0) { + fail <- FALSE + x.new[is.na(x.new) & x.bak == x[i]] <- found[1L] + } + + # try abbreviation + found <- AMR::antibiotics[which(paste0("(", AMR::antibiotics$abbr, ")") %like% x[i]),]$atc + if (length(found) > 0) { + fail <- FALSE + x.new[is.na(x.new) & x.bak == x[i]] <- found[1L] + } + + # not found + if (fail == TRUE) { + failures <- c(failures, x[i]) + } + } + + failures <- failures[!failures %in% c(NA, NULL, NaN)] + if (length(failures) > 0) { + warning("These values could not be coerced to a valid atc: ", + paste('"', unique(failures), '"', sep = "", collapse = ', '), + ".", + call. = FALSE) + } + class(x.new) <- "atc" + attr(x.new, 'package') <- 'AMR' + x.new +} + +#' @rdname as.atc +#' @export +guess_atc <- as.atc + +#' @rdname as.atc +#' @export +is.atc <- function(x) { + identical(class(x), "atc") +} + + +#' @exportMethod print.atc +#' @export +#' @noRd +print.atc <- function(x, ...) { + cat("Class 'atc'\n") + print.default(as.character(x), quote = FALSE) +} + +#' @exportMethod as.data.frame.atc +#' @export +#' @noRd +as.data.frame.atc <- function (x, ...) { + # same as as.data.frame.character but with removed stringsAsFactors + nm <- paste(deparse(substitute(x), width.cutoff = 500L), + collapse = " ") + if (!"nm" %in% names(list(...))) { + as.data.frame.vector(x, ..., nm = nm) + } else { + as.data.frame.vector(x, ...) + } +} + +#' @exportMethod pull.atc +#' @export +#' @importFrom dplyr pull +#' @noRd +pull.atc <- function(.data, ...) { + pull(as.data.frame(.data), ...) +} + +atc_get_property <- function(atc, param) { + if (!is.atc(atc)) { + atc <- as.atc(atc) + } + suppressWarnings( + data.frame(atc = atc, stringsAsFactors = FALSE) %>% + left_join(AMR::antibiotics, by = "atc") %>% + pull(param) + ) +} + +#' Get antibiotic property based on ATC +#' +#' Use these functions to return a specific property of an antibiotic from the \code{\link{antibiotics}} data set, based on their ATC code. +#' @param atc a valid ATC code, created with \code{\link{as.atc}} +#' @rdname atc.property +#' @name atc.property +#' @export +atc.official <- function(atc) { + atc_get_property(atc, "official") +} + +#' @rdname atc.property +#' @export +atc.official_nl <- function(atc) { + atc_get_property(atc, "official_nl") +} + +#' @rdname atc.property +#' @export +atc.trivial_nl <- function(atc) { + atc_get_property(atc, "trivial_nl") +} + +#' @rdname atc.property +#' @export +atc.certe <- function(atc) { + atc_get_property(atc, "certe") +} + +#' @rdname atc.property +#' @export +atc.umcg <- function(atc) { + atc_get_property(atc, "umcg") +} + #' Properties of an ATC code #' #' Gets data from the WHO to determine properties of an ATC (e.g. an antibiotic) like name, defined daily dose (DDD) or standard unit. \cr \strong{This function requires an internet connection.} @@ -203,87 +382,3 @@ atc_ddd <- function(atc_code, ...) { atc_property(atc_code = atc_code, property = "ddd", ...) } - -#' Find ATC code based on antibiotic property -#' -#' Use this function to determine the ATC code of one or more antibiotics. The dataset \code{\link{antibiotics}} will be searched for abbreviations, official names and trade names. -#' @param x character vector to determine \code{ATC} code -#' @export -#' @importFrom dplyr %>% filter slice pull -#' @details In the ATC classification system, the active substances are classified in a hierarchy with five different levels. The system has fourteen main anatomical/pharmacological groups or 1st levels. Each ATC main group is divided into 2nd levels which could be either pharmacological or therapeutic groups. The 3rd and 4th levels are chemical, pharmacological or therapeutic subgroups and the 5th level is the chemical substance. The 2nd, 3rd and 4th levels are often used to identify pharmacological subgroups when that is considered more appropriate than therapeutic or chemical subgroups. -#' Source: \url{https://www.whocc.no/atc/structure_and_principles/} -#' @return Character (vector). -#' @seealso \code{\link{antibiotics}} for the dataframe that is being used to determine ATC's. -#' @examples -#' # These examples all return "J01FA01", the ATC code of Erythromycin: -#' guess_atc("J01FA01") -#' guess_atc("Erythromycin") -#' guess_atc("eryt") -#' guess_atc("ERYT") -#' guess_atc("ERY") -#' guess_atc("Erythrocin") # Trade name -#' guess_atc("Eryzole") # Trade name -#' guess_atc("Pediamycin") # Trade name -guess_atc <- function(x) { - - # use this later to further fill AMR::antibiotics - - # drug <- "Ciprofloxacin" - # url <- xml2::read_html(paste0("https://www.ncbi.nlm.nih.gov/pccompound?term=", drug)) %>% - # html_nodes(".rslt") %>% - # .[[1]] %>% - # html_nodes(".title a") %>% - # html_attr("href") %>% - # gsub("/compound/", "/rest/pug_view/data/compound/", ., fixed = TRUE) %>% - # paste0("/XML/?response_type=display") - # synonyms <- url %>% - # read_xml() %>% - # xml_contents() %>% .[[6]] %>% - # xml_contents() %>% .[[8]] %>% - # xml_contents() %>% .[[3]] %>% - # xml_contents() %>% .[[3]] %>% - # xml_contents() %>% - # paste() %>% - # .[. %like% "StringValueList"] %>% - # gsub("[]", "", .) - - - for (i in 1:length(x)) { - - # first try atc - found <- AMR::antibiotics %>% filter(atc == x[i]) - - if (nrow(found) == 0) { - # try abbreviation of molis and glims - found <- AMR::antibiotics %>% filter(tolower(molis) == tolower(x[i]) | tolower(umcg) == tolower(x[i])) - } - - if (nrow(found) == 0) { - # try exact official name - found <- AMR::antibiotics[which(tolower(AMR::antibiotics$official) == tolower(x[i])),] - } - - if (nrow(found) == 0) { - # try trade name - found <- AMR::antibiotics[which(paste0("(", AMR::antibiotics$trade_name, ")") %like% x[i]),] - } - - if (nrow(found) == 0) { - # try abbreviation - found <- AMR::antibiotics[which(paste0("(", AMR::antibiotics$abbr, ")") %like% x[i]),] - } - # if (nrow(found) == 0) { - # # loosely try official name - # found <- AMR::antibiotics[which(AMR::antibiotics$official %like% x[i]),] - # } - - if (nrow(found) != 0) { - x[i] <- found %>% - slice(1) %>% - pull(atc) - } else { - x[i] <- NA - } - } - x -} diff --git a/R/bactid.R b/R/bactid.R index 2e7848f3..e80be3f2 100644 --- a/R/bactid.R +++ b/R/bactid.R @@ -380,3 +380,79 @@ as.data.frame.bactid <- function (x, ...) { pull.bactid <- function(.data, ...) { pull(as.data.frame(.data), ...) } + +bactid_get_property <- function(bactid, param) { + if (!is.bactid(bactid)) { + bactid <- as.bactid(bactid) + } + suppressWarnings( + data.frame(bactid = bactid, stringsAsFactors = FALSE) %>% + left_join(AMR::microorganisms, by = "bactid") %>% + pull(param) + ) +} + +#' Get microbial property based on `bactid` +#' +#' Use these functions to return a specific property of a microorganism from the \code{\link{microorganisms}} data set, based on their \code{bactid}. Get such an ID with \code{\link{as.bactid}}. +#' @param bactid a valid bactid code, created with \code{\link{as.bactid}} +#' @rdname bactid.property +#' @name bactid.property +#' @export +bactid.family <- function(bactid) { + bactid_get_property(bactid, "family") +} + +#' @rdname bactid.property +#' @export +bactid.genus <- function(bactid) { + bactid_get_property(bactid, "genus") +} + +#' @rdname bactid.property +#' @export +bactid.species <- function(bactid) { + bactid_get_property(bactid, "species") +} + +#' @rdname bactid.property +#' @export +bactid.subspecies <- function(bactid) { + bactid_get_property(bactid, "subspecies") +} + +#' @rdname bactid.property +#' @export +bactid.fullname <- function(bactid) { + bactid_get_property(bactid, "fullname") +} + +#' @rdname bactid.property +#' @export +bactid.type <- function(bactid) { + bactid_get_property(bactid, "type") +} + +#' @rdname bactid.property +#' @export +bactid.gramstain <- function(bactid) { + bactid_get_property(bactid, "gramstain") +} + +#' @rdname bactid.property +#' @export +bactid.aerobic <- function(bactid) { + bactid_get_property(bactid, "aerobic") +} + +#' @rdname bactid.property +#' @export +bactid.type_nl <- function(bactid) { + bactid_get_property(bactid, "type_nl") +} + +#' @rdname bactid.property +#' @export +bactid.gramstain_nl <- function(bactid) { + bactid_get_property(bactid, "gramstain_nl") +} diff --git a/R/data.R b/R/data.R index bf0c763d..b32d1f64 100755 --- a/R/data.R +++ b/R/data.R @@ -22,7 +22,7 @@ #' @format A data.frame with 420 observations and 18 variables: #' \describe{ #' \item{\code{atc}}{ATC code, like \code{J01CR02}} -#' \item{\code{molis}}{MOLIS code, like \code{amcl}} +#' \item{\code{certe}}{Certe code, like \code{amcl}} #' \item{\code{umcg}}{UMCG code, like \code{AMCL}} #' \item{\code{abbr}}{Abbreviation as used by many countries, to be used for \code{\link{guess_atc}}} #' \item{\code{official}}{Official name by the WHO, like \code{"Amoxicillin and enzyme inhibitor"}} @@ -42,6 +42,25 @@ #' } #' @source - World Health Organization: \url{https://www.whocc.no/atc_ddd_index/} \cr - EUCAST - Expert rules intrinsic exceptional V3.1 \cr - MOLIS (LIS of Certe): \url{https://www.certe.nl} \cr - GLIMS (LIS of UMCG): \url{https://www.umcg.nl} #' @seealso \code{\link{microorganisms}} +# use this later to further fill AMR::antibiotics +# drug <- "Ciprofloxacin" +# url <- xml2::read_html(paste0("https://www.ncbi.nlm.nih.gov/pccompound?term=", drug)) %>% +# html_nodes(".rslt") %>% +# .[[1]] %>% +# html_nodes(".title a") %>% +# html_attr("href") %>% +# gsub("/compound/", "/rest/pug_view/data/compound/", ., fixed = TRUE) %>% +# paste0("/XML/?response_type=display") +# synonyms <- url %>% +# read_xml() %>% +# xml_contents() %>% .[[6]] %>% +# xml_contents() %>% .[[8]] %>% +# xml_contents() %>% .[[3]] %>% +# xml_contents() %>% .[[3]] %>% +# xml_contents() %>% +# paste() %>% +# .[. %like% "StringValueList"] %>% +# gsub("[]", "", .) # abbr and trade_name created with: # https://hs.unr.edu/Documents/dhs/chs/NVPHTC/antibiotic_refeference_guide.pdf # antibiotics %>% diff --git a/R/eucast.R b/R/eucast.R index 15e5006c..d0aa7c9c 100755 --- a/R/eucast.R +++ b/R/eucast.R @@ -695,38 +695,3 @@ EUCAST_rules <- function(tbl, interpretive_reading <- function(...) { EUCAST_rules(...) } - -#' Poperties of a microorganism -#' -#' @param bactid ID of a microorganisme, like \code{"STAAUR} and \code{"ESCCOL} -#' @param property One of the values \code{bactid}, \code{bactsys}, \code{family}, \code{genus}, \code{species}, \code{subspecies}, \code{fullname}, \code{type}, \code{gramstain}, \code{aerobic} -#' @export -#' @importFrom dplyr %>% filter select -#' @seealso \code{\link{microorganisms}} -mo_property <- function(bactid, property = 'fullname') { - - mocode <- as.character(bactid) - - for (i in 1:length(mocode)) { - bug <- mocode[i] - - if (!is.na(bug)) { - result = tryCatch({ - mocode[i] <- - AMR::microorganisms %>% - filter(bactid == bug) %>% - select(property) %>% - unlist() %>% - as.character() - }, error = function(error_condition) { - warning('Code ', bug, ' not found in bacteria list.') - }, finally = { - if (mocode[i] == bug & !property %in% c('bactid', 'bactsys')) { - mocode[i] <- NA - } - }) - } - - } - mocode -} diff --git a/R/globals.R b/R/globals.R index 7c765670..aa0ffdb4 100755 --- a/R/globals.R +++ b/R/globals.R @@ -30,6 +30,7 @@ globalVariables(c('abname', 'atc', 'bactid', 'C_chisq_sim', + 'certe', 'cnt', 'count', 'Count', @@ -54,7 +55,6 @@ globalVariables(c('abname', 'MIC', 'microorganisms', 'mocode', - 'molis', 'n', 'na.omit', 'observations', diff --git a/R/classes.R b/R/mic.R similarity index 63% rename from R/classes.R rename to R/mic.R index 3fc42974..25bbeb78 100755 --- a/R/classes.R +++ b/R/mic.R @@ -16,186 +16,6 @@ # GNU General Public License for more details. # # ==================================================================== # -#' Class 'rsi' -#' -#' This transforms a vector to a new class \code{rsi}, which is an ordered factor with levels \code{S < I < R}. Invalid antimicrobial interpretations will be translated as \code{NA} with a warning. -#' @rdname as.rsi -#' @param x vector -#' @details The function \code{is.rsi.eligible} returns \code{TRUE} when a columns contains only valid antimicrobial interpretations (S and/or I and/or R), and \code{FALSE} otherwise. -#' @return Ordered factor with new class \code{rsi} and new attribute \code{package} -#' @keywords rsi -#' @export -#' @importFrom dplyr %>% -#' @seealso \code{\link{as.mic}} -#' @examples -#' rsi_data <- as.rsi(c(rep("S", 474), rep("I", 36), rep("R", 370))) -#' rsi_data <- as.rsi(c(rep("S", 474), rep("I", 36), rep("R", 370), "A", "B", "C")) -#' is.rsi(rsi_data) -#' -#' # this can also coerce combined MIC/RSI values: -#' as.rsi("<= 0.002; S") # will return S -#' -#' plot(rsi_data) # for percentages -#' barplot(rsi_data) # for frequencies -#' freq(rsi_data) # frequency table with informative header -#' -#' # fastest way to transform all columns with already valid AB results to class `rsi`: -#' library(dplyr) -#' septic_patients %>% -#' mutate_if(is.rsi.eligible, -#' as.rsi) -as.rsi <- function(x) { - if (is.rsi(x)) { - x - } else { - - x <- x %>% unlist() - x.bak <- x - - na_before <- x[is.na(x) | x == ''] %>% length() - # remove all spaces - x <- gsub(' +', '', x) - # remove all MIC-like values: numbers, operators and periods - x <- gsub('[0-9.,;:<=>]+', '', x) - # disallow more than 3 characters - x[nchar(x) > 3] <- NA - # set to capitals - x <- toupper(x) - # remove all invalid characters - x <- gsub('[^RSI]+', '', x) - # in cases of "S;S" keep S, but in case of "S;I" make it NA - x <- gsub('^S+$', 'S', x) - x <- gsub('^I+$', 'I', x) - x <- gsub('^R+$', 'R', x) - x[!x %in% c('S', 'I', 'R')] <- NA - na_after <- x[is.na(x) | x == ''] %>% length() - - if (na_before != na_after) { - list_missing <- x.bak[is.na(x) & !is.na(x.bak) & x.bak != ''] %>% - unique() %>% - sort() - list_missing <- paste0('"', list_missing , '"', collapse = ", ") - warning(na_after - na_before, ' results truncated (', - round(((na_after - na_before) / length(x)) * 100), - '%) that were invalid antimicrobial interpretations: ', - list_missing, call. = FALSE) - } - - x <- x %>% factor(levels = c("S", "I", "R"), ordered = TRUE) - class(x) <- c('rsi', 'ordered', 'factor') - attr(x, 'package') <- 'AMR' - x - } -} - -#' @rdname as.rsi -#' @export -#' @importFrom dplyr %>% -is.rsi <- function(x) { - class(x) %>% identical(c('rsi', 'ordered', 'factor')) -} - -#' @rdname as.rsi -#' @export -#' @importFrom dplyr %>% -is.rsi.eligible <- function(x) { - distinct_val <- x %>% unique() %>% sort() %>% as.character() - distinct_val <- distinct_val[!is.na(distinct_val) & trimws(distinct_val) != ""] - distinct_val_rsi <- as.character(suppressWarnings(as.rsi(distinct_val))) - - length(distinct_val) > 0 & - identical(distinct_val, distinct_val_rsi) -} - -#' @exportMethod print.rsi -#' @export -#' @importFrom dplyr %>% -#' @noRd -print.rsi <- function(x, ...) { - cat("Class 'rsi'\n") - print(as.character(x), quote = FALSE) -} - -#' @exportMethod summary.rsi -#' @export -#' @noRd -summary.rsi <- function(object, ...) { - x <- object - c( - "Mode" = 'rsi', - "" = sum(is.na(x)), - "Sum S" = sum(x == "S", na.rm = TRUE), - "Sum IR" = sum(x %in% c("I", "R"), na.rm = TRUE), - "-Sum R" = sum(x == "R", na.rm = TRUE), - "-Sum I" = sum(x == "I", na.rm = TRUE) - ) -} - -#' @exportMethod plot.rsi -#' @export -#' @importFrom dplyr %>% group_by summarise filter mutate if_else n_distinct -#' @importFrom graphics plot text -#' @noRd -plot.rsi <- function(x, ...) { - x_name <- deparse(substitute(x)) - - data <- data.frame(x = x, - y = 1, - stringsAsFactors = TRUE) %>% - group_by(x) %>% - summarise(n = sum(y)) %>% - filter(!is.na(x)) %>% - mutate(s = round((n / sum(n)) * 100, 1)) - data$x <- factor(data$x, levels = c('S', 'I', 'R'), ordered = TRUE) - - ymax <- if_else(max(data$s) > 95, 105, 100) - - plot(x = data$x, - y = data$s, - lwd = 2, - col = c('green', 'orange', 'red'), - ylim = c(0, ymax), - ylab = 'Percentage', - xlab = 'Antimicrobial Interpretation', - main = paste('Susceptibility Analysis of', x_name), - axes = FALSE, - ...) - # x axis - axis(side = 1, at = 1:n_distinct(data$x), labels = levels(data$x), lwd = 0) - # y axis, 0-100% - axis(side = 2, at = seq(0, 100, 5)) - - text(x = data$x, - y = data$s + 4, - labels = paste0(data$s, '% (n = ', data$n, ')')) -} - - -#' @exportMethod barplot.rsi -#' @export -#' @importFrom dplyr %>% group_by summarise filter mutate if_else n_distinct -#' @importFrom graphics barplot axis -#' @noRd -barplot.rsi <- function(height, ...) { - x <- height - x_name <- deparse(substitute(height)) - - data <- data.frame(rsi = x, cnt = 1) %>% - group_by(rsi) %>% - summarise(cnt = sum(cnt)) %>% - droplevels() - - barplot(table(x), - col = c('green3', 'orange2', 'red3'), - xlab = 'Antimicrobial Interpretation', - main = paste('Susceptibility Analysis of', x_name), - ylab = 'Frequency', - axes = FALSE, - ...) - # y axis, 0-100% - axis(side = 2, at = seq(0, max(data$cnt) + max(data$cnt) * 1.1, by = 25)) -} - #' Class 'mic' #' #' This transforms a vector to a new class \code{mic}, which is an ordered factor with valid MIC values as levels. Invalid MIC values will be translated as \code{NA} with a warning. diff --git a/R/portion.R b/R/portion.R index 17d9a7d8..f8ff7d8e 100755 --- a/R/portion.R +++ b/R/portion.R @@ -251,3 +251,48 @@ portion_df <- function(data, res } + + +#' Calculate resistance of isolates +#' +#' This function is deprecated. Use the \code{\link{portion}} functions instead. +#' @inheritParams portion +#' @param ab1,ab2 vector (or column) with antibiotic interpretations. It will be transformed internally with \code{\link{as.rsi}} if needed. +#' @param interpretation antimicrobial interpretation to check for +#' @param ... deprecated parameters to support usage on older versions +#' @importFrom dplyr tibble case_when +#' @export +rsi <- function(ab1, + ab2 = NULL, + interpretation = "IR", + minimum = 30, + as_percent = FALSE, + ...) { + + if (all(is.null(ab2))) { + df <- tibble(ab1 = ab1) + } else { + df <- tibble(ab1 = ab1, + ab2 = ab2) + } + + result <- case_when( + interpretation == "S" ~ portion_S(df, minimum = minimum, as_percent = FALSE), + interpretation %in% c("SI", "IS") ~ portion_SI(df, minimum = minimum, as_percent = FALSE), + interpretation == "I" ~ portion_I(df, minimum = minimum, as_percent = FALSE), + interpretation %in% c("RI", "IR") ~ portion_IR(df, minimum = minimum, as_percent = FALSE), + interpretation == "R" ~ portion_R(df, minimum = minimum, as_percent = FALSE), + TRUE ~ -1 + ) + if (result == -1) { + stop("invalid interpretation") + } + + .Deprecated(new = paste0("portion_", interpretation)) + + if (as_percent == TRUE) { + percent(result, force_zero = TRUE) + } else { + result + } +} diff --git a/R/rsi.R b/R/rsi.R index cef5cfa1..db86965d 100644 --- a/R/rsi.R +++ b/R/rsi.R @@ -16,46 +16,182 @@ # GNU General Public License for more details. # # ==================================================================== # -#' Calculate resistance of isolates +#' Class 'rsi' #' -#' This function is deprecated. Use the \code{\link{portion}} functions instead. -#' @inheritParams portion -#' @param ab1,ab2 vector (or column) with antibiotic interpretations. It will be transformed internally with \code{\link{as.rsi}} if needed. -#' @param interpretation antimicrobial interpretation to check for -#' @param ... deprecated parameters to support usage on older versions -#' @importFrom dplyr tibble case_when +#' This transforms a vector to a new class \code{rsi}, which is an ordered factor with levels \code{S < I < R}. Invalid antimicrobial interpretations will be translated as \code{NA} with a warning. +#' @rdname as.rsi +#' @param x vector +#' @details The function \code{is.rsi.eligible} returns \code{TRUE} when a columns contains only valid antimicrobial interpretations (S and/or I and/or R), and \code{FALSE} otherwise. +#' @return Ordered factor with new class \code{rsi} and new attribute \code{package} +#' @keywords rsi #' @export -rsi <- function(ab1, - ab2 = NULL, - interpretation = "IR", - minimum = 30, - as_percent = FALSE, - ...) { - - if (all(is.null(ab2))) { - df <- tibble(ab1 = ab1) +#' @importFrom dplyr %>% +#' @seealso \code{\link{as.mic}} +#' @examples +#' rsi_data <- as.rsi(c(rep("S", 474), rep("I", 36), rep("R", 370))) +#' rsi_data <- as.rsi(c(rep("S", 474), rep("I", 36), rep("R", 370), "A", "B", "C")) +#' is.rsi(rsi_data) +#' +#' # this can also coerce combined MIC/RSI values: +#' as.rsi("<= 0.002; S") # will return S +#' +#' plot(rsi_data) # for percentages +#' barplot(rsi_data) # for frequencies +#' freq(rsi_data) # frequency table with informative header +#' +#' # fastest way to transform all columns with already valid AB results to class `rsi`: +#' library(dplyr) +#' septic_patients %>% +#' mutate_if(is.rsi.eligible, +#' as.rsi) +as.rsi <- function(x) { + if (is.rsi(x)) { + x } else { - df <- tibble(ab1 = ab1, - ab2 = ab2) - } - result <- case_when( - interpretation == "S" ~ portion_S(df, minimum = minimum, as_percent = FALSE), - interpretation %in% c("SI", "IS") ~ portion_SI(df, minimum = minimum, as_percent = FALSE), - interpretation == "I" ~ portion_I(df, minimum = minimum, as_percent = FALSE), - interpretation %in% c("RI", "IR") ~ portion_IR(df, minimum = minimum, as_percent = FALSE), - interpretation == "R" ~ portion_R(df, minimum = minimum, as_percent = FALSE), - TRUE ~ -1 - ) - if (result == -1) { - stop("invalid interpretation") - } + x <- x %>% unlist() + x.bak <- x - .Deprecated(new = paste0("portion_", interpretation)) + na_before <- x[is.na(x) | x == ''] %>% length() + # remove all spaces + x <- gsub(' +', '', x) + # remove all MIC-like values: numbers, operators and periods + x <- gsub('[0-9.,;:<=>]+', '', x) + # disallow more than 3 characters + x[nchar(x) > 3] <- NA + # set to capitals + x <- toupper(x) + # remove all invalid characters + x <- gsub('[^RSI]+', '', x) + # in cases of "S;S" keep S, but in case of "S;I" make it NA + x <- gsub('^S+$', 'S', x) + x <- gsub('^I+$', 'I', x) + x <- gsub('^R+$', 'R', x) + x[!x %in% c('S', 'I', 'R')] <- NA + na_after <- x[is.na(x) | x == ''] %>% length() - if (as_percent == TRUE) { - percent(result, force_zero = TRUE) - } else { - result + if (na_before != na_after) { + list_missing <- x.bak[is.na(x) & !is.na(x.bak) & x.bak != ''] %>% + unique() %>% + sort() + list_missing <- paste0('"', list_missing , '"', collapse = ", ") + warning(na_after - na_before, ' results truncated (', + round(((na_after - na_before) / length(x)) * 100), + '%) that were invalid antimicrobial interpretations: ', + list_missing, call. = FALSE) + } + + x <- x %>% factor(levels = c("S", "I", "R"), ordered = TRUE) + class(x) <- c('rsi', 'ordered', 'factor') + attr(x, 'package') <- 'AMR' + x } } + +#' @rdname as.rsi +#' @export +#' @importFrom dplyr %>% +is.rsi <- function(x) { + class(x) %>% identical(c('rsi', 'ordered', 'factor')) +} + +#' @rdname as.rsi +#' @export +#' @importFrom dplyr %>% +is.rsi.eligible <- function(x) { + distinct_val <- x %>% unique() %>% sort() %>% as.character() + distinct_val <- distinct_val[!is.na(distinct_val) & trimws(distinct_val) != ""] + distinct_val_rsi <- as.character(suppressWarnings(as.rsi(distinct_val))) + + length(distinct_val) > 0 & + identical(distinct_val, distinct_val_rsi) +} + +#' @exportMethod print.rsi +#' @export +#' @importFrom dplyr %>% +#' @noRd +print.rsi <- function(x, ...) { + cat("Class 'rsi'\n") + print(as.character(x), quote = FALSE) +} + +#' @exportMethod summary.rsi +#' @export +#' @noRd +summary.rsi <- function(object, ...) { + x <- object + c( + "Mode" = 'rsi', + "" = sum(is.na(x)), + "Sum S" = sum(x == "S", na.rm = TRUE), + "Sum IR" = sum(x %in% c("I", "R"), na.rm = TRUE), + "-Sum R" = sum(x == "R", na.rm = TRUE), + "-Sum I" = sum(x == "I", na.rm = TRUE) + ) +} + +#' @exportMethod plot.rsi +#' @export +#' @importFrom dplyr %>% group_by summarise filter mutate if_else n_distinct +#' @importFrom graphics plot text +#' @noRd +plot.rsi <- function(x, ...) { + x_name <- deparse(substitute(x)) + + data <- data.frame(x = x, + y = 1, + stringsAsFactors = TRUE) %>% + group_by(x) %>% + summarise(n = sum(y)) %>% + filter(!is.na(x)) %>% + mutate(s = round((n / sum(n)) * 100, 1)) + data$x <- factor(data$x, levels = c('S', 'I', 'R'), ordered = TRUE) + + ymax <- if_else(max(data$s) > 95, 105, 100) + + plot(x = data$x, + y = data$s, + lwd = 2, + col = c('green', 'orange', 'red'), + ylim = c(0, ymax), + ylab = 'Percentage', + xlab = 'Antimicrobial Interpretation', + main = paste('Susceptibility Analysis of', x_name), + axes = FALSE, + ...) + # x axis + axis(side = 1, at = 1:n_distinct(data$x), labels = levels(data$x), lwd = 0) + # y axis, 0-100% + axis(side = 2, at = seq(0, 100, 5)) + + text(x = data$x, + y = data$s + 4, + labels = paste0(data$s, '% (n = ', data$n, ')')) +} + + +#' @exportMethod barplot.rsi +#' @export +#' @importFrom dplyr %>% group_by summarise filter mutate if_else n_distinct +#' @importFrom graphics barplot axis +#' @noRd +barplot.rsi <- function(height, ...) { + x <- height + x_name <- deparse(substitute(height)) + + data <- data.frame(rsi = x, cnt = 1) %>% + group_by(rsi) %>% + summarise(cnt = sum(cnt)) %>% + droplevels() + + barplot(table(x), + col = c('green3', 'orange2', 'red3'), + xlab = 'Antimicrobial Interpretation', + main = paste('Susceptibility Analysis of', x_name), + ylab = 'Frequency', + axes = FALSE, + ...) + # y axis, 0-100% + axis(side = 2, at = seq(0, max(data$cnt) + max(data$cnt) * 1.1, by = 25)) +} diff --git a/README.md b/README.md index 2c889954..410f9ec2 100755 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This R package was created for academic research by PhD students of the Faculty of Medical Sciences of the [University of Groningen](https://www.rug.nl) and the Medical Microbiology & Infection Prevention (MMBI) department of the [University Medical Center Groningen (UMCG)](https://www.umcg.nl). -:arrow_forward: Download it with `install.packages("AMR")` or see below for other possibilities. +:arrow_forward: Get it with `install.packages("AMR")` or see below for other possibilities. Read all changes and new functions in [NEWS.md](NEWS.md). ## Authors Matthijs S. Berends1,2,a, @@ -40,31 +40,31 @@ Erwin E.A. Hassing2, ## Why this package? This R package was intended to make microbial epidemiology easier. Most functions contain extensive help pages to get started. -With `AMR` you can: -* Calculate the resistance (and even co-resistance) of microbial isolates with the `portion_R`, `portion_IR`, `portion_I`, `portion_SI` and `portion_S` functions, that can also be used with the `dplyr` package (e.g. in conjunction with `summarise`) -* Plot AMR results with `geom_rsi`, a function made for the `ggplot2` package -* Predict antimicrobial resistance for the nextcoming years using logistic regression models with the `resistance_predict` function -* Apply [EUCAST rules to isolates](http://www.eucast.org/expert_rules_and_intrinsic_resistance/) with the `EUCAST_rules` function -* Identify first isolates of every patient [using guidelines from the CLSI](https://clsi.org/standards/products/microbiology/documents/m39/) (Clinical and Laboratory Standards Institute) with the `first_isolate` function - * You can also identify first *weighted* isolates of every patient, an adjusted version of the CLSI guideline. This takes into account key antibiotics of every strain and compares them. The following 12 antibiotics will be used as key antibiotics at default: - * Universal: amoxicillin, amoxicillin/clavlanic acid, cefuroxime, piperacillin/tazobactam, ciprofloxacin, trimethoprim/sulfamethoxazole - * Specific for Gram-positives: vancomycin, teicoplanin, tetracycline, erythromycin, oxacillin, rifampicin - * Specific for Gram-negatives: gentamicin, tobramycin, colistin, cefotaxime, ceftazidime, meropenem -* Categorise *Staphylococci* into Coagulase Negative *Staphylococci* (CoNS) and Coagulase Positve *Staphylococci* (CoPS) according to [Karsten Becker *et al.*](https://www.ncbi.nlm.nih.gov/pmc/articles/pmid/25278577/) -* Categorise *Streptococci* into Lancefield groups -* Get antimicrobial ATC properties from the WHO Collaborating Centre for Drug Statistics Methodology ([WHOCC](https://www.whocc.no/atc_ddd_methodology/who_collaborating_centre/)), to be able to: - * Translate antibiotic codes (like *AMOX*), official names (like *amoxicillin*) and even trade names (like *Amoxil* or *Trimox*) to an [ATC code](https://www.whocc.no/atc_ddd_index/?code=J01CA04&showdescription=no) (like *J01CA04*) and vice versa with the `abname` function - * Get the latest antibiotic properties like hierarchic groups and [defined daily dose](https://en.wikipedia.org/wiki/Defined_daily_dose) (DDD) with units and administration form from the WHOCC website with the `atc_property` function -* Conduct descriptive statistics: calculate kurtosis, skewness and create frequency tables +This `AMR` package basically does four important things: -And it contains: -* A recent data set with ~2500 human pathogenic microorganisms, including family, genus, species, gram stain and aerobic/anaerobic -* A recent data set with all antibiotics as defined by the [WHOCC](https://www.whocc.no/atc_ddd_methodology/who_collaborating_centre/), including ATC code, official name and DDD's -* An example data set `septic_patients`, consisting of 2000 blood culture isolates from anonymised septic patients between 2001 and 2017. +1. It **cleanses existing data**, by transforming it to reproducible and profound *classes*, making the most efficient use of R. These function all use artificial intelligence to get expected results: -With the `MDRO` function (abbreviation of Multi Drug Resistant Organisms), you can check your isolates for exceptional resistance with country-specific guidelines or EUCAST rules. Currently guidelines for Germany and the Netherlands are supported. Please suggest addition of your own country here: [https://github.com/msberends/AMR/issues/new](https://github.com/msberends/AMR/issues/new?title=New%20guideline%20for%20MDRO&body=%3C--%20Please%20add%20your%20country%20code,%20guideline%20name,%20version%20and%20source%20below%20and%20remove%20this%20line--%3E). + * Use `as.bactid` to get an ID of a microorganism. It takes almost any text as input that looks like the name or code of a microorganism like "E. coli", "esco" and "esccol". Moreover, it can group all coagulase negative and positive *Staphylococci*, and can transform *Streptococci* into Lancefield groups. This package has a database of ~2500 different (potential) human pathogenic microorganisms. + * Use `as.rsi` to transform values to valid antimicrobial results. It produces just S, I or R based on your input and warns about invalid values. Even values like "<=0.002; S" (combined MIC/RSI) will result in "S". + * Use `as.mic` to cleanse your MIC values. It produces a so-called factor (in SPSS calls this *ordinal*) with valid MIC values as levels. A value like "<=0.002; S" (combined MIC/RSI) will result in "<=0.002". + * Use `as.atc` to get the ATC code of an antibiotic as defined by the WHO. This package contains a database with most LIS codes, official names, DDDs and even trade names of antibiotics. For example, the values "Furabid", "Furadantine", "nitro" will return the ATC code of Nitrofurantoine. + +2. It **enhances existing data** and **adds new data** from data sets included in this package. -**Read all changes and new functions in [NEWS.md](NEWS.md).** + * Use `EUCAST_rules` to apply [EUCAST expert rules to isolates](http://www.eucast.org/expert_rules_and_intrinsic_resistance/). + * Use `MDRO` (abbreviation of Multi Drug Resistant Organisms) to check your isolates for exceptional resistance with country-specific guidelines with or EUCAST rules. Currently, national guidelines for Germany and the Netherlands are supported. + * Data set `microorganisms` contains the family, genus, species, subspecies, colloqual name and Gram stain of almost 2500 microorganisms. This enables e.g. resistance analysis of different antibiotics per Gram stain. + * Data set `antibiotics` contains the ATC code, LIS codes, official name, trivial name, trade name and DDD of both oral and parenteral administration. + * Use `first_isolate` to identify the first isolates of every patient [using guidelines from the CLSI](https://clsi.org/standards/products/microbiology/documents/m39/) (Clinical and Laboratory Standards Institute). * You can also identify first *weighted* isolates of every patient, an adjusted version of the CLSI guideline. This takes into account key antibiotics of every strain and compares them. + +3. It **analyses the data** with convenient functions that use well-known methods. + + * Calculate the resistance (and even co-resistance) of microbial isolates with the `portion_R`, `portion_IR`, `portion_I`, `portion_SI` and `portion_S` functions, that can also be used with the `dplyr` package (e.g. in conjunction with `summarise`) + * Plot AMR results with `geom_rsi`, a function made for the `ggplot2` package + * Predict antimicrobial resistance for the nextcoming years using logistic regression models with the `resistance_predict` function + * Conduct descriptive statistics to enhance base R: calculate kurtosis, skewness and create frequency tables + +4. It **teaches the user** how to use all the above actions, by showing many examples in the help pages. The package contains an example data set called `septic_patients`. This data set, consisting of 2000 blood culture isolates from anonymised septic patients between 2001 and 2017 in the Northern Netherlands, is real and genuine data. ## How to get it? All versions of this package [are published on CRAN](http://cran.r-project.org/package=AMR), the official R network with a peer-reviewed submission process. diff --git a/data/antibiotics.rda b/data/antibiotics.rda index 27221fdac2acfcd21d823d9938cc061305cab87c..669ad455427741e577856ab5fbba6233aa3f8db2 100755 GIT binary patch delta 12612 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 L7!w&DRPz4-2uVE0 diff --git a/man/abname.Rd b/man/abname.Rd index c74ccafb..0b22e2e6 100644 --- a/man/abname.Rd +++ b/man/abname.Rd @@ -7,24 +7,24 @@ \code{\link{antibiotics}} } \usage{ -abname(abcode, from = c("guess", "atc", "molis", "umcg"), +abname(abcode, from = c("guess", "atc", "certe", "umcg"), to = "official", textbetween = " + ", tolower = FALSE) } \arguments{ \item{abcode}{a code or name, like \code{"AMOX"}, \code{"AMCL"} or \code{"J01CA04"}} -\item{from, to}{type to transform from and to. See \code{\link{antibiotics}} for its column names. WIth \code{from = "guess"} the from will be guessed from \code{"atc"}, \code{"molis"} and \code{"umcg"}. When using \code{to = "atc"}, the ATC code will be searched using \code{\link{guess_atc}}.} +\item{from, to}{type to transform from and to. See \code{\link{antibiotics}} for its column names. WIth \code{from = "guess"} the from will be guessed from \code{"atc"}, \code{"certe"} and \code{"umcg"}. When using \code{to = "atc"}, the ATC code will be searched using \code{\link{as.atc}}.} \item{textbetween}{text to put between multiple returned texts} \item{tolower}{return output as lower case with function \code{\link{tolower}}.} } \description{ -Convert antibiotic codes (from a laboratory information system like MOLIS or GLIMS) to a (trivial) antibiotic name or ATC code, or vice versa. This uses the data from \code{\link{antibiotics}}. +Convert antibiotic codes to a (trivial) antibiotic name or ATC code, or vice versa. This uses the data from \code{\link{antibiotics}}. } \examples{ abname("AMCL") -# "amoxicillin and enzyme inhibitor" +# "Amoxicillin and beta-lactamase inhibitor" # It is quite flexible at default (having `from = "guess"`) abname(c("amox", "J01CA04", "Trimox", "dispermox", "Amoxil")) @@ -47,6 +47,10 @@ abname("AMCL", to = "atc") # specific codes for University Medical Center Groningen (UMCG): abname("J01CR02", from = "atc", to = "umcg") # "AMCL" + +# specific codes for Certe: +abname("J01CR02", from = "atc", to = "certe") +# "amcl" } \keyword{ab} \keyword{antibiotics} diff --git a/man/antibiotics.Rd b/man/antibiotics.Rd index db8cf86e..c166949c 100755 --- a/man/antibiotics.Rd +++ b/man/antibiotics.Rd @@ -7,7 +7,7 @@ \format{A data.frame with 420 observations and 18 variables: \describe{ \item{\code{atc}}{ATC code, like \code{J01CR02}} - \item{\code{molis}}{MOLIS code, like \code{amcl}} + \item{\code{certe}}{Certe code, like \code{amcl}} \item{\code{umcg}}{UMCG code, like \code{AMCL}} \item{\code{abbr}}{Abbreviation as used by many countries, to be used for \code{\link{guess_atc}}} \item{\code{official}}{Official name by the WHO, like \code{"Amoxicillin and enzyme inhibitor"}} diff --git a/man/guess_atc.Rd b/man/as.atc.Rd old mode 100755 new mode 100644 similarity index 54% rename from man/guess_atc.Rd rename to man/as.atc.Rd index ccfe9906..0a276ce1 --- a/man/guess_atc.Rd +++ b/man/as.atc.Rd @@ -1,35 +1,43 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/atc.R -\name{guess_atc} +\name{as.atc} +\alias{as.atc} +\alias{atc} \alias{guess_atc} +\alias{is.atc} \title{Find ATC code based on antibiotic property} \usage{ +as.atc(x) + guess_atc(x) + +is.atc(x) } \arguments{ \item{x}{character vector to determine \code{ATC} code} } \value{ -Character (vector). +Character (vector) with class \code{"act"}. Unknown values will return \code{NA}. } \description{ Use this function to determine the ATC code of one or more antibiotics. The dataset \code{\link{antibiotics}} will be searched for abbreviations, official names and trade names. } \details{ -In the ATC classification system, the active substances are classified in a hierarchy with five different levels. The system has fourteen main anatomical/pharmacological groups or 1st levels. Each ATC main group is divided into 2nd levels which could be either pharmacological or therapeutic groups. The 3rd and 4th levels are chemical, pharmacological or therapeutic subgroups and the 5th level is the chemical substance. The 2nd, 3rd and 4th levels are often used to identify pharmacological subgroups when that is considered more appropriate than therapeutic or chemical subgroups. +In the ATC classification system, the active substances are classified in a hierarchy with five different levels. The system has fourteen main anatomical/pharmacological groups or 1st levels. Each ATC main group is divided into 2nd levels which could be either pharmacological or therapeutic groups. The 3rd and 4th levels are chemical, pharmacological or therapeutic subgroups and the 5th level is the chemical substance. The 2nd, 3rd and 4th levels are often used to identify pharmacological subgroups when that is considered more appropriate than therapeutic or chemical subgroups. Source: \url{https://www.whocc.no/atc/structure_and_principles/} } \examples{ # These examples all return "J01FA01", the ATC code of Erythromycin: -guess_atc("J01FA01") -guess_atc("Erythromycin") -guess_atc("eryt") -guess_atc("ERYT") -guess_atc("ERY") -guess_atc("Erythrocin") # Trade name -guess_atc("Eryzole") # Trade name -guess_atc("Pediamycin") # Trade name +as.atc("J01FA01") +as.atc("Erythromycin") +as.atc("eryt") +as.atc("ERYT") +as.atc("ERY") +as.atc("Erythrocin") # Trade name +as.atc("Eryzole") # Trade name +as.atc("Pediamycin") # Trade name } \seealso{ \code{\link{antibiotics}} for the dataframe that is being used to determine ATC's. } +\keyword{atc} diff --git a/man/as.mic.Rd b/man/as.mic.Rd index 2031cedd..02e0ef53 100755 --- a/man/as.mic.Rd +++ b/man/as.mic.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/classes.R +% Please edit documentation in R/mic.R \name{as.mic} \alias{as.mic} \alias{is.mic} diff --git a/man/as.rsi.Rd b/man/as.rsi.Rd index bb3549ff..92a97c24 100755 --- a/man/as.rsi.Rd +++ b/man/as.rsi.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/classes.R +% Please edit documentation in R/rsi.R \name{as.rsi} \alias{as.rsi} \alias{is.rsi} diff --git a/man/atc.property.Rd b/man/atc.property.Rd new file mode 100644 index 00000000..23494a0f --- /dev/null +++ b/man/atc.property.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/atc.R +\name{atc.property} +\alias{atc.property} +\alias{atc.official} +\alias{atc.official_nl} +\alias{atc.trivial_nl} +\alias{atc.certe} +\alias{atc.umcg} +\title{Get antibiotic property based on ATC} +\usage{ +atc.official(atc) + +atc.official_nl(atc) + +atc.trivial_nl(atc) + +atc.certe(atc) + +atc.umcg(atc) +} +\arguments{ +\item{atc}{a valid ATC code, created with \code{\link{as.atc}}} +} +\description{ +Use these functions to return a specific property of an antibiotic from the \code{\link{antibiotics}} data set, based on their ATC code. +} diff --git a/man/bactid.property.Rd b/man/bactid.property.Rd new file mode 100644 index 00000000..cf05b4c4 --- /dev/null +++ b/man/bactid.property.Rd @@ -0,0 +1,42 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/bactid.R +\name{bactid.property} +\alias{bactid.property} +\alias{bactid.family} +\alias{bactid.genus} +\alias{bactid.species} +\alias{bactid.subspecies} +\alias{bactid.fullname} +\alias{bactid.type} +\alias{bactid.gramstain} +\alias{bactid.aerobic} +\alias{bactid.type_nl} +\alias{bactid.gramstain_nl} +\title{Get microbial property based on `bactid`} +\usage{ +bactid.family(bactid) + +bactid.genus(bactid) + +bactid.species(bactid) + +bactid.subspecies(bactid) + +bactid.fullname(bactid) + +bactid.type(bactid) + +bactid.gramstain(bactid) + +bactid.aerobic(bactid) + +bactid.type_nl(bactid) + +bactid.gramstain_nl(bactid) +} +\arguments{ +\item{bactid}{a valid bactid code, created with \code{\link{as.bactid}}} +} +\description{ +Use these functions to return a specific property of a microorganism from the \code{\link{microorganisms}} data set, based on their \code{bactid}. Get such an ID with \code{\link{as.bactid}}. +} diff --git a/man/mo_property.Rd b/man/mo_property.Rd deleted file mode 100755 index 8bc92e46..00000000 --- a/man/mo_property.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eucast.R -\name{mo_property} -\alias{mo_property} -\title{Poperties of a microorganism} -\usage{ -mo_property(bactid, property = "fullname") -} -\arguments{ -\item{bactid}{ID of a microorganisme, like \code{"STAAUR} and \code{"ESCCOL}} - -\item{property}{One of the values \code{bactid}, \code{bactsys}, \code{family}, \code{genus}, \code{species}, \code{subspecies}, \code{fullname}, \code{type}, \code{gramstain}, \code{aerobic}} -} -\description{ -Poperties of a microorganism -} -\seealso{ -\code{\link{microorganisms}} -} diff --git a/man/rsi.Rd b/man/rsi.Rd index 60430bc0..d925892b 100644 --- a/man/rsi.Rd +++ b/man/rsi.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/rsi.R +% Please edit documentation in R/portion.R \name{rsi} \alias{rsi} \title{Calculate resistance of isolates} diff --git a/tests/testthat/test-abname.R b/tests/testthat/test-abname.R index 44b4358f..9a1f963b 100644 --- a/tests/testthat/test-abname.R +++ b/tests/testthat/test-abname.R @@ -5,7 +5,7 @@ test_that("abname works", { expect_equal(abname(c("AMOX", "GENT")), c("Amoxicillin", "Gentamicin")) expect_equal(abname(c("AMOX+GENT")), "Amoxicillin + gentamicin") expect_equal(abname("AMOX", from = 'umcg'), "Amoxicillin") - expect_equal(abname("amox", from = 'molis', tolower = TRUE), "amoxicillin") + expect_equal(abname("amox", from = 'certe', tolower = TRUE), "amoxicillin") expect_equal(abname("J01CA04", from = 'atc'), "Amoxicillin") expect_equal(abname(c("amox", "J01CA04", "Trimox", "dispermox", "Amoxil")), rep("Amoxicillin", 5)) diff --git a/tests/testthat/test-atc.R b/tests/testthat/test-atc.R index 180d8176..35812998 100755 --- a/tests/testthat/test-atc.R +++ b/tests/testthat/test-atc.R @@ -22,14 +22,25 @@ test_that("atc_property works", { }) test_that("guess_atc works", { - expect_equal(guess_atc(c("J01FA01", + expect_equal(as.character(guess_atc(c("J01FA01", "Erythromycin", "eryt", "ERYT", "ERY", "Erythrocin", "Eryzole", - "Pediamycin")), + "Pediamycin"))), rep("J01FA01", 8)) + expect_identical(class(as.atc("amox")), "atc") + + +}) + +test_that("atc.property works", { + expect_equal(atc.certe("J01CA04"), "amox") + expect_equal(atc.umcg("J01CA04"), "AMOX") + expect_equal(atc.official("J01CA04"), "Amoxicillin") + expect_equal(atc.official_nl("J01CA04"), "Amoxicilline") + expect_equal(atc.trivial_nl("J01CA04"), "Amoxicilline") }) diff --git a/tests/testthat/test-bactid.R b/tests/testthat/test-bactid.R index a86f58dc..66b5f623 100644 --- a/tests/testthat/test-bactid.R +++ b/tests/testthat/test-bactid.R @@ -108,3 +108,16 @@ test_that("as.bactid works", { NA_character_) }) + +test_that("bactid.property works", { + expect_equal(bactid.family("E. coli"), "Enterobacteriaceae") + expect_equal(bactid.genus("E. coli"), "Escherichia") + expect_equal(bactid.species("E. coli"), "coli") + expect_equal(bactid.subspecies("E. coli"), NA_character_) + expect_equal(bactid.fullname("E. coli"), "Escherichia coli") + expect_equal(bactid.type("E. coli"), "Bacteria") + expect_equal(bactid.gramstain("E. coli"), "Negative rods") + expect_equal(bactid.aerobic("E. coli"), TRUE) + expect_equal(bactid.type_nl("E. coli"), "Bacterie") + expect_equal(bactid.gramstain_nl("E. coli"), "Negatieve staven") +}) diff --git a/tests/testthat/test-eucast.R b/tests/testthat/test-eucast.R index fd9cc69e..2efc363c 100755 --- a/tests/testthat/test-eucast.R +++ b/tests/testthat/test-eucast.R @@ -32,8 +32,3 @@ test_that("EUCAST rules work", { stringsAsFactors = FALSE) expect_equal(suppressWarnings(EUCAST_rules(a, info = FALSE)), b) }) - -test_that("MO properties work", { - expect_equal(mo_property("ESCCOL"), "Escherichia coli") - expect_equal(mo_property("STAAUR"), "Staphylococcus aureus") -}) diff --git a/tests/testthat/test-classes.R b/tests/testthat/test-mic.R similarity index 52% rename from tests/testthat/test-classes.R rename to tests/testthat/test-mic.R index a0bfe504..cb6797fc 100755 --- a/tests/testthat/test-classes.R +++ b/tests/testthat/test-mic.R @@ -1,25 +1,4 @@ -context("classes.R") - -test_that("rsi works", { - expect_true(as.rsi("S") < as.rsi("I")) - expect_true(as.rsi("I") < as.rsi("R")) - expect_true(as.rsi("R") > as.rsi("S")) - expect_true(is.rsi(as.rsi("S"))) - - # print plots, should not raise errors - barplot(as.rsi(c("S", "I", "R"))) - plot(as.rsi(c("S", "I", "R"))) - print(as.rsi(c("S", "I", "R"))) - - expect_equal(suppressWarnings(as.logical(as.rsi("INVALID VALUE"))), NA) - - expect_equal(summary(as.rsi(c("S", "R"))), c("Mode" = 'rsi', - "" = "0", - "Sum S" = "1", - "Sum IR" = "1", - "-Sum R" = "1", - "-Sum I" = "0")) -}) +context("mic.R") test_that("mic works", { expect_true(as.mic(8) == as.mic("8")) diff --git a/tests/testthat/test-rsi.R b/tests/testthat/test-rsi.R new file mode 100644 index 00000000..b3aa6a42 --- /dev/null +++ b/tests/testthat/test-rsi.R @@ -0,0 +1,22 @@ +context("rsi.R") + +test_that("rsi works", { + expect_true(as.rsi("S") < as.rsi("I")) + expect_true(as.rsi("I") < as.rsi("R")) + expect_true(as.rsi("R") > as.rsi("S")) + expect_true(is.rsi(as.rsi("S"))) + + # print plots, should not raise errors + barplot(as.rsi(c("S", "I", "R"))) + plot(as.rsi(c("S", "I", "R"))) + print(as.rsi(c("S", "I", "R"))) + + expect_equal(suppressWarnings(as.logical(as.rsi("INVALID VALUE"))), NA) + + expect_equal(summary(as.rsi(c("S", "R"))), c("Mode" = 'rsi', + "" = "0", + "Sum S" = "1", + "Sum IR" = "1", + "-Sum R" = "1", + "-Sum I" = "0")) +}) diff --git a/vignettes/AMR.Rmd b/vignettes/AMR.Rmd new file mode 100755 index 00000000..7cafa85e --- /dev/null +++ b/vignettes/AMR.Rmd @@ -0,0 +1,58 @@ +--- +title: "Introduction to the AMR package" +author: "Matthijs S. Berends" +output: + rmarkdown::html_vignette: + toc: true +vignette: > + %\VignetteIndexEntry{Creating Frequency Tables} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r setup, include = FALSE, results = 'markup'} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#" +) +``` + +This R package was intended to make microbial epidemiology easier. Most functions contain extensive help pages to get started. + +This `AMR` package basically does four important things: + +1. It **cleanses existing data**, by transforming it to reproducible and profound *classes*, making the most efficient use of R. These function all use artificial intelligence to get expected results: + + * Use `as.bactid` to get an ID of a microorganism. It takes almost any text as input that looks like the name or code of a microorganism like "E. coli", "esco" and "esccol". Moreover, it can group all coagulase negative and positive *Staphylococci*, and can transform *Streptococci* into Lancefield groups. This package has a database of ~2500 different (potential) human pathogenic microorganisms. + * Use `as.rsi` to transform values to valid antimicrobial results. It produces just S, I or R based on your input and warns about invalid values. Even values like "<=0.002; S" (combined MIC/RSI) will result in "S". + * Use `as.mic` to cleanse your MIC values. It produces a so-called factor (in SPSS calls this *ordinal*) with valid MIC values as levels. A value like "<=0.002; S" (combined MIC/RSI) will result in "<=0.002". + * Use `as.atc` to get the ATC code of an antibiotic as defined by the WHO. This package contains a database with most LIS codes, official names, DDDs and even trade names of antibiotics. For example, the values "Furabid", "Furadantine", "nitro" will return the ATC code of Nitrofurantoine. + +2. It **enhances existing data** and **adds new data** from data sets included in this package. + + * Use `EUCAST_rules` to apply [EUCAST expert rules to isolates](http://www.eucast.org/expert_rules_and_intrinsic_resistance/). + * Use `MDRO` (abbreviation of Multi Drug Resistant Organisms) to check your isolates for exceptional resistance with country-specific guidelines with or EUCAST rules. Currently, national guidelines for Germany and the Netherlands are supported. + * Data set `microorganisms` contains the family, genus, species, subspecies, colloqual name and Gram stain of almost 2500 microorganisms. This enables e.g. resistance analysis of different antibiotics per Gram stain. + * Data set `antibiotics` contains the ATC code, LIS codes, official name, trivial name, trade name and DDD of both oral and parenteral administration. + * Use `first_isolate` to identify the first isolates of every patient [using guidelines from the CLSI](https://clsi.org/standards/products/microbiology/documents/m39/) (Clinical and Laboratory Standards Institute). * You can also identify first *weighted* isolates of every patient, an adjusted version of the CLSI guideline. This takes into account key antibiotics of every strain and compares them. + +3. It **analyses the data** with convenient functions that use well-known methods. + + * Calculate the resistance (and even co-resistance) of microbial isolates with the `portion_R`, `portion_IR`, `portion_I`, `portion_SI` and `portion_S` functions, that can also be used with the `dplyr` package (e.g. in conjunction with `summarise`) + * Plot AMR results with `geom_rsi`, a function made for the `ggplot2` package + * Predict antimicrobial resistance for the nextcoming years using logistic regression models with the `resistance_predict` function + * Conduct descriptive statistics to enhance base R: calculate kurtosis, skewness and create frequency tables + +4. It **teaches the user** how to use all the above actions, by showing many examples in the help pages. The package contains an example data set called `septic_patients`. This data set, consisting of 2000 blood culture isolates from anonymised septic patients between 2001 and 2017 in the Northern Netherlands, is real and genuine data. + + +---- +```{r, echo = FALSE} +# this will print "2018" in 2018, and "2018-yyyy" after 2018. +yrs <- c(2018:format(Sys.Date(), "%Y")) +yrs <- c(min(yrs), max(yrs)) +yrs <- paste(unique(yrs), collapse = "-") +``` +AMR, (c) `r yrs`, `r packageDescription("AMR")$URL` + +Licensed under the [GNU General Public License v2.0](https://github.com/msberends/AMR/blob/master/LICENSE).