diff --git a/.gitlab-ci.R b/.gitlab-ci.R index ae44cf34..4a2628c5 100644 --- a/.gitlab-ci.R +++ b/.gitlab-ci.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # install_if_needed <- function(pkg, repos, quiet) { diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 95459424..156d744b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # stages: diff --git a/DESCRIPTION b/DESCRIPTION index f1406b8d..2afed23f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: AMR -Version: 0.6.1.9001 -Date: 2019-03-29 +Version: 0.6.1.9002 +Date: 2019-04-05 Title: Antimicrobial Resistance Analysis Authors@R: c( person( diff --git a/NAMESPACE b/NAMESPACE index 37afc23d..4ec62f58 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -40,7 +40,6 @@ S3method(summary,mic) S3method(summary,mo) S3method(summary,rsi) export("%like%") -export(EUCAST_rules) export(ab_atc) export(ab_certe) export(ab_name) @@ -82,6 +81,7 @@ export(count_all) export(count_df) export(eucast_exceptional_phenotypes) export(eucast_rules) +export(eucast_rules_file) export(facet_rsi) export(filter_1st_cephalosporins) export(filter_2nd_cephalosporins) @@ -108,11 +108,8 @@ export(get_mo_source) export(ggplot_rsi) export(ggplot_rsi_predict) export(guess_ab_col) -export(guess_atc) -export(guess_mo) export(header) export(inner_join_microorganisms) -export(interpretive_reading) export(is.atc) export(is.mic) export(is.mo) @@ -281,6 +278,7 @@ importFrom(graphics,points) importFrom(graphics,text) importFrom(hms,is.hms) importFrom(knitr,kable) +importFrom(microbenchmark,microbenchmark) importFrom(rlang,as_label) importFrom(rlang,enquos) importFrom(rlang,eval_tidy) diff --git a/NEWS.md b/NEWS.md index e8d65843..f4bf27a5 100755 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,11 @@ # AMR 0.6.1.9001 **Note: latest development version** +#### Changed +* Removed deprecated functions `guess_mo()`, `guess_atc()`, `EUCAST_rules()`, `interpretive_reading()` +* Added more old taxonomic names to the `microorganisms.old` data set, which leads to better results finding when using the `as.mo()` function +* Frequency tables of microbial IDs speed improvement +* Removed all hardcoded EUCAST rules and replaced them with a new reference file: `./inst/eucast/eucast.tsv`. # AMR 0.6.1 diff --git a/R/abname.R b/R/abname.R index a561ae68..87ae33d0 100755 --- a/R/abname.R +++ b/R/abname.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Name of an antibiotic diff --git a/R/age.R b/R/age.R index 0df17e96..0eca8995 100755 --- a/R/age.R +++ b/R/age.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Age in years of individuals diff --git a/R/amr.R b/R/amr.R index bdbc9b5a..3c5edef9 100644 --- a/R/amr.R +++ b/R/amr.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' The \code{AMR} Package @@ -64,4 +64,6 @@ #' \url{https://gitlab.com/msberends/AMR/issues} #' @name AMR #' @rdname AMR +# # prevent NOTE on R >= 3.6 +#' @importFrom microbenchmark microbenchmark NULL diff --git a/R/atc.R b/R/atc.R index b609dceb..626e399b 100755 --- a/R/atc.R +++ b/R/atc.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Transform to ATC code diff --git a/R/atc_online.R b/R/atc_online.R index c201b51a..469c28be 100644 --- a/R/atc_online.R +++ b/R/atc_online.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Get ATC properties from WHOCC website diff --git a/R/atc_property.R b/R/atc_property.R index 36a98486..b3a55ded 100755 --- a/R/atc_property.R +++ b/R/atc_property.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Property of an antibiotic diff --git a/R/availability.R b/R/availability.R index 17b620a7..cec00f1e 100644 --- a/R/availability.R +++ b/R/availability.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Check availability of columns diff --git a/R/catalogue_of_life.R b/R/catalogue_of_life.R index f15d7c80..812e5e0d 100755 --- a/R/catalogue_of_life.R +++ b/R/catalogue_of_life.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' The Catalogue of Life @@ -33,7 +33,7 @@ #' \item{All ~55,000 (sub)species from the kingdoms of Archaea, Bacteria and Protozoa} #' \item{All ~3,500 (sub)species from these orders of the kingdom of Fungi: Eurotiales, Onygenales, Pneumocystales, Saccharomycetales, Schizosaccharomycetales and Tremellales. The kingdom of Fungi is a very large taxon with almost 300,000 different (sub)species, of which most are not microbial (but rather macroscopic, like mushrooms). Because of this, not all fungi fit the scope of this package and including everything would tremendously slow down our algorithms too. By only including the aforementioned taxonomic orders, the most relevant fungi are covered (like all species of \emph{Aspergillus}, \emph{Candida}, \emph{Cryptococcus}, \emph{Histplasma}, \emph{Pneumocystis}, \emph{Saccharomyces} and \emph{Trichophyton}).} #' \item{All ~2,000 (sub)species from ~100 other relevant genera, from the kingdoms of Animalia and Plantae (like \emph{Strongyloides} and \emph{Taenia})} -#' \item{All ~15,000 previously accepted names of included (sub)species that have been taxonomically renamed} +#' \item{All ~21,000 previously accepted names of included (sub)species that have been taxonomically renamed} #' \item{The complete taxonomic tree of all included (sub)species: from kingdom to subspecies} #' \item{The responsible author(s) and year of scientific publication} #' } diff --git a/R/count.R b/R/count.R index b1036cdc..0d56ce1f 100755 --- a/R/count.R +++ b/R/count.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Count isolates @@ -74,15 +74,15 @@ #' # Count co-resistance between amoxicillin/clav acid and gentamicin, #' # so we can see that combination therapy does a lot more than mono therapy. #' # Please mind that `portion_S` calculates percentages right away instead. -#' count_S(septic_patients$amcl) # S = 1057 (67.1%) -#' count_all(septic_patients$amcl) # n = 1576 +#' count_S(septic_patients$amcl) # S = 1342 (71.4%) +#' count_all(septic_patients$amcl) # n = 1879 #' #' count_S(septic_patients$gent) # S = 1372 (74.0%) #' count_all(septic_patients$gent) # n = 1855 #' #' with(septic_patients, -#' count_S(amcl, gent)) # S = 1396 (92.0%) -#' with(septic_patients, # n = 1517 +#' count_S(amcl, gent)) # S = 1660 (92.3%) +#' with(septic_patients, # n = 1798 #' n_rsi(amcl, gent)) #' #' # Get portions S/I/R immediately of all rsi columns diff --git a/R/data.R b/R/data.R index 68bd43d8..5ca6e1c9 100755 --- a/R/data.R +++ b/R/data.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Data set with ~500 antibiotics @@ -183,14 +183,14 @@ catalogue_of_life <- list( #' #' A data set containing old (previously valid or accepted) taxonomic names according to the Catalogue of Life. This data set is used internally by \code{\link{as.mo}}. #' @inheritSection catalogue_of_life Catalogue of Life -#' @format A \code{\link{data.frame}} with 16,911 observations and 4 variables: +#' @format A \code{\link{data.frame}} with 21,342 observations and 4 variables: #' \describe{ -#' \item{\code{col_id}}{Catalogue of Life ID} -#' \item{\code{tsn_new}}{New Catalogue of Life ID} -#' \item{\code{fullname}}{Old taxonomic name of the microorganism} +#' \item{\code{col_id}}{Catalogue of Life ID that was originally given} +#' \item{\code{col_id_new}}{New Catalogue of Life ID that responds to an entry in the \code{\link{microorganisms}} data set} +#' \item{\code{fullname}}{Old full taxonomic name of the microorganism} #' \item{\code{ref}}{Author(s) and year of concerning scientific publication} #' } -#' @source [3] Catalogue of Life: Annual Checklist (public online database), \url{www.catalogueoflife.org}. +#' @source Catalogue of Life: Annual Checklist (public online taxonomic database), \url{www.catalogueoflife.org} (check included annual version with \code{\link{catalogue_of_life_version}()}). #' @inheritSection AMR Read more on our website! #' @seealso \code{\link{as.mo}} \code{\link{mo_property}} \code{\link{microorganisms}} "microorganisms.old" @@ -261,3 +261,23 @@ catalogue_of_life <- list( #' } #' @inheritSection AMR Read more on our website! "WHONET" + +# transforms data set to data.frame with only ASCII values, to comply with CRAN policies +dataset_UTF8_to_ASCII <- function(df) { + trans <- function(vect) { + iconv(vect, from = "UTF-8", to = "ASCII//TRANSLIT") + } + df <- as.data.frame(df, stringsAsFactors = FALSE) + for (i in 1:NCOL(df)) { + col <- df[, i] + if (is.factor(col)) { + levels(col) <- trans(levels(col)) + } else if (is.character(col)) { + col <- trans(col) + } else { + col + } + df[, i] <- col + } + df +} diff --git a/R/deprecated.R b/R/deprecated.R index ca95703b..a05acce7 100755 --- a/R/deprecated.R +++ b/R/deprecated.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Deprecated functions @@ -47,20 +47,6 @@ ratio <- function(x, ratio) { sum(x, na.rm = TRUE) * (ratio / sum(ratio, na.rm = TRUE)) } -#' @rdname AMR-deprecated -#' @export -guess_mo <- function(...) { - .Deprecated(new = "as.mo", package = "AMR") - as.mo(...) -} - -#' @rdname AMR-deprecated -#' @export -guess_atc <- function(...) { - .Deprecated(new = "as.atc", package = "AMR") - as.atc(...) -} - #' @rdname AMR-deprecated #' @export ab_property <- function(...) { diff --git a/R/eucast_rules.R b/R/eucast_rules.R index d6022f2e..79d160a6 100755 --- a/R/eucast_rules.R +++ b/R/eucast_rules.R @@ -16,19 +16,31 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # +# global variables +EUCAST_RULES_FILE_LOCATION <- system.file("eucast/eucast_rules.tsv", package = "AMR") +EUCAST_VERSION_BREAKPOINTS <- "9.0, 2019" +EUCAST_VERSION_EXPERT_RULES <- "3.1, 2016" + #' EUCAST rules #' #' Apply susceptibility rules as defined by the European Committee on Antimicrobial Susceptibility Testing (EUCAST, \url{http://eucast.org}), see \emph{Source}. This includes (1) expert rules, (2) intrinsic resistance and (3) inferred resistance as defined in their breakpoint tables. -#' @param tbl table with antibiotic columns, like e.g. \code{amox} and \code{amcl} +#' @param x data with antibiotic columns, like e.g. \code{amox} and \code{amcl} #' @param info print progress #' @param rules a character vector that specifies which rules should be applied - one or more of \code{c("breakpoints", "expert", "other", "all")} #' @param verbose a logical to indicate whether extensive info should be returned as a \code{data.frame} with info about which rows and columns are effected. It runs all EUCAST rules, but will not be applied to an output - only an informative \code{data.frame} with changes will be returned as output. #' @param amcl,amik,amox,ampi,azit,azlo,aztr,cefa,cfep,cfot,cfox,cfra,cfta,cftr,cfur,chlo,cipr,clar,clin,clox,coli,czol,dapt,doxy,erta,eryt,fosf,fusi,gent,imip,kana,levo,linc,line,mero,mezl,mino,moxi,nali,neom,neti,nitr,norf,novo,oflo,oxac,peni,pipe,pita,poly,pris,qida,rifa,roxi,siso,teic,tetr,tica,tige,tobr,trim,trsu,vanc column name of an antibiotic, see Antibiotics #' @param ... parameters that are passed on to \code{eucast_rules} #' @inheritParams first_isolate +#' @details +#' The file used for applying all EUCAST rules can be retrieved with \code{\link{eucast_rules_file}()}. It returns an easily readable data set containing all rules. The original TSV file (tab separated file) that is being read by this function can be found when running this command: \cr +#' \code{AMR::EUCAST_RULES_FILE_LOCATION} (without brackets). +#' +#' In the source code it is located under \href{https://gitlab.com/msberends/AMR/blob/master/inst/eucast/eucast_rules.tsv}{\code{./inst/eucast/eucast_rules.tsv}}. +#' +#' \strong{Note:} When ampicillin (J01CA01) is not available but amoxicillin (J01CA04) is, the latter will be used for all rules where there is a dependency on ampicillin. These drugs are interchangeable when it comes to expression of antimicrobial resistance. #' @section Antibiotics: #' To define antibiotics column names, leave as it is to determine it automatically with \code{\link{guess_ab_col}} or input a text (case-insensitive) or use \code{NULL} to skip a column (e.g. \code{tica = NULL}). Non-existing columns will anyway be skipped with a warning. #' @@ -99,9 +111,9 @@ #' @keywords interpretive eucast reading resistance #' @rdname eucast_rules #' @export -#' @importFrom dplyr %>% select pull mutate_at vars +#' @importFrom dplyr %>% select pull mutate_at vars group_by summarise n #' @importFrom crayon bold bgGreen bgYellow bgRed black green blue italic strip_style -#' @return The input of \code{tbl}, possibly with edited values of antibiotics. Or, if \code{verbose = TRUE}, a \code{data.frame} with all original and new values of the affected bug-drug combinations. +#' @return The input of \code{tbl_}, possibly with edited values of antibiotics. Or, if \code{verbose = TRUE}, a \code{data.frame} with all original and new values of the affected bug-drug combinations. #' @source #' \itemize{ #' \item{ @@ -118,6 +130,8 @@ #' \url{http://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Breakpoint_tables/v_9.0_Breakpoint_Tables.xlsx} #' } #' } +#' +#' For editing the reference file (which is available with \code{\link{eucast_rules_file}}), these values can all be used for target antibiotics: aminoglycosides, tetracyclines, polymyxins, macrolides, glycopeptides, streptogramins, cephalosporins, cephalosporins_without_cfta, carbapenems, aminopenicillins, ureidopenicillins, fluoroquinolones, all_betalactams, and all separate four letter codes like amcl. They can be separated by comma: \code{"amcl, fluoroquinolones"}. The mo_property can be any column name from the \code{\link{microorganisms}} data set, or \code{genus_species} or \code{gramstain}. This file contains references to the 'Burkholderia cepacia complex'. The species in this group can be found in: LiPuma JJ, 2015 (PMID 16217180). #' @inheritSection AMR Read more on our website! #' @examples #' a <- eucast_rules(septic_patients) @@ -160,7 +174,7 @@ #' # do not apply EUCAST rules, but rather get a a data.frame #' # with 18 rows, containing all details about the transformations: #' c <- eucast_rules(a, verbose = TRUE) -eucast_rules <- function(tbl, +eucast_rules <- function(x, col_mo = NULL, info = TRUE, rules = c("breakpoints", "expert", "other", "all"), @@ -227,116 +241,121 @@ eucast_rules <- function(tbl, tobr = guess_ab_col(), trim = guess_ab_col(), trsu = guess_ab_col(), - vanc = guess_ab_col()) { + vanc = guess_ab_col(), + ...) { - EUCAST_VERSION_BREAKPOINTS <- "9.0, 2019" - EUCAST_VERSION_EXPERT_RULES <- "3.1, 2016" - if (!is.data.frame(tbl)) { - stop("`tbl` must be a data frame.", call. = FALSE) + # support old `tbl` parameter + if ("tbl" %in% names(list(...))) { + x <- list(...)$tbl + } + + tbl_ <- x + + if (!is.data.frame(tbl_)) { + stop("`tbl_` must be a data frame.", call. = FALSE) } # try to find columns based on type # -- mo if (is.null(col_mo)) { - col_mo <- search_type_in_df(tbl = tbl, type = "mo") + col_mo <- search_type_in_df(tbl = tbl_, type = "mo") } if (is.null(col_mo)) { stop("`col_mo` must be set.", call. = FALSE) } if (!all(rules %in% c("breakpoints", "expert", "other", "all"))) { - stop("Parameter `rules` must be one or more of: 'breakpoints', 'expert', 'other', 'all'.") + stop("`rules` must be one or more of: 'breakpoints', 'expert', 'other', 'all'.") } if (is.null(col_mo)) { - stop("Parameter `col_mo` must be set") + stop("`col_mo` must be set") } warned <- FALSE - changed_results <- 0 txt_error <- function() { cat("", bgRed(black(" ERROR ")), "\n") } txt_warning <- function() { if (warned == FALSE) { cat("", bgYellow(black(" WARNING ")), "\n") }; warned <<- TRUE } - txt_ok <- function() { + txt_ok <- function(no_of_changes) { if (warned == FALSE) { - if (changed_results > 0) { - if (changed_results == 1) { - cat(blue(" (1 change)\n")) + if (no_of_changes > 0) { + if (no_of_changes == 1) { + cat(blue(" (1 new change)\n")) } else { - cat(blue(paste0(" (", changed_results, " changes)\n"))) + cat(blue(paste0(" (", no_of_changes, " new changes)\n"))) } } else { - cat(green(" (no changes)\n")) + cat(green(" (no new changes)\n")) } warned <<- FALSE } } # check columns - if (identical(amcl, as.name("guess_ab_col"))) { amcl <- guess_ab_col(tbl, "amcl", verbose = verbose) } - if (identical(amik, as.name("guess_ab_col"))) { amik <- guess_ab_col(tbl, "amik", verbose = verbose) } - if (identical(amox, as.name("guess_ab_col"))) { amox <- guess_ab_col(tbl, "amox", verbose = verbose) } - if (identical(ampi, as.name("guess_ab_col"))) { ampi <- guess_ab_col(tbl, "ampi", verbose = verbose) } - if (identical(azit, as.name("guess_ab_col"))) { azit <- guess_ab_col(tbl, "azit", verbose = verbose) } - if (identical(azlo, as.name("guess_ab_col"))) { azlo <- guess_ab_col(tbl, "azlo", verbose = verbose) } - if (identical(aztr, as.name("guess_ab_col"))) { aztr <- guess_ab_col(tbl, "aztr", verbose = verbose) } - if (identical(cefa, as.name("guess_ab_col"))) { cefa <- guess_ab_col(tbl, "cefa", verbose = verbose) } - if (identical(cfep, as.name("guess_ab_col"))) { cfep <- guess_ab_col(tbl, "cfep", verbose = verbose) } - if (identical(cfot, as.name("guess_ab_col"))) { cfot <- guess_ab_col(tbl, "cfot", verbose = verbose) } - if (identical(cfox, as.name("guess_ab_col"))) { cfox <- guess_ab_col(tbl, "cfox", verbose = verbose) } - if (identical(cfra, as.name("guess_ab_col"))) { cfra <- guess_ab_col(tbl, "cfra", verbose = verbose) } - if (identical(cfta, as.name("guess_ab_col"))) { cfta <- guess_ab_col(tbl, "cfta", verbose = verbose) } - if (identical(cftr, as.name("guess_ab_col"))) { cftr <- guess_ab_col(tbl, "cftr", verbose = verbose) } - if (identical(cfur, as.name("guess_ab_col"))) { cfur <- guess_ab_col(tbl, "cfur", verbose = verbose) } - if (identical(chlo, as.name("guess_ab_col"))) { chlo <- guess_ab_col(tbl, "chlo", verbose = verbose) } - if (identical(cipr, as.name("guess_ab_col"))) { cipr <- guess_ab_col(tbl, "cipr", verbose = verbose) } - if (identical(clar, as.name("guess_ab_col"))) { clar <- guess_ab_col(tbl, "clar", verbose = verbose) } - if (identical(clin, as.name("guess_ab_col"))) { clin <- guess_ab_col(tbl, "clin", verbose = verbose) } - if (identical(clox, as.name("guess_ab_col"))) { clox <- guess_ab_col(tbl, "clox", verbose = verbose) } - if (identical(coli, as.name("guess_ab_col"))) { coli <- guess_ab_col(tbl, "coli", verbose = verbose) } - if (identical(czol, as.name("guess_ab_col"))) { czol <- guess_ab_col(tbl, "czol", verbose = verbose) } - if (identical(dapt, as.name("guess_ab_col"))) { dapt <- guess_ab_col(tbl, "dapt", verbose = verbose) } - if (identical(doxy, as.name("guess_ab_col"))) { doxy <- guess_ab_col(tbl, "doxy", verbose = verbose) } - if (identical(erta, as.name("guess_ab_col"))) { erta <- guess_ab_col(tbl, "erta", verbose = verbose) } - if (identical(eryt, as.name("guess_ab_col"))) { eryt <- guess_ab_col(tbl, "eryt", verbose = verbose) } - if (identical(fosf, as.name("guess_ab_col"))) { fosf <- guess_ab_col(tbl, "fosf", verbose = verbose) } - if (identical(fusi, as.name("guess_ab_col"))) { fusi <- guess_ab_col(tbl, "fusi", verbose = verbose) } - if (identical(gent, as.name("guess_ab_col"))) { gent <- guess_ab_col(tbl, "gent", verbose = verbose) } - if (identical(imip, as.name("guess_ab_col"))) { imip <- guess_ab_col(tbl, "imip", verbose = verbose) } - if (identical(kana, as.name("guess_ab_col"))) { kana <- guess_ab_col(tbl, "kana", verbose = verbose) } - if (identical(levo, as.name("guess_ab_col"))) { levo <- guess_ab_col(tbl, "levo", verbose = verbose) } - if (identical(linc, as.name("guess_ab_col"))) { linc <- guess_ab_col(tbl, "linc", verbose = verbose) } - if (identical(line, as.name("guess_ab_col"))) { line <- guess_ab_col(tbl, "line", verbose = verbose) } - if (identical(mero, as.name("guess_ab_col"))) { mero <- guess_ab_col(tbl, "mero", verbose = verbose) } - if (identical(mezl, as.name("guess_ab_col"))) { mezl <- guess_ab_col(tbl, "mezl", verbose = verbose) } - if (identical(mino, as.name("guess_ab_col"))) { mino <- guess_ab_col(tbl, "mino", verbose = verbose) } - if (identical(moxi, as.name("guess_ab_col"))) { moxi <- guess_ab_col(tbl, "moxi", verbose = verbose) } - if (identical(nali, as.name("guess_ab_col"))) { nali <- guess_ab_col(tbl, "nali", verbose = verbose) } - if (identical(neom, as.name("guess_ab_col"))) { neom <- guess_ab_col(tbl, "neom", verbose = verbose) } - if (identical(neti, as.name("guess_ab_col"))) { neti <- guess_ab_col(tbl, "neti", verbose = verbose) } - if (identical(nitr, as.name("guess_ab_col"))) { nitr <- guess_ab_col(tbl, "nitr", verbose = verbose) } - if (identical(norf, as.name("guess_ab_col"))) { norf <- guess_ab_col(tbl, "norf", verbose = verbose) } - if (identical(novo, as.name("guess_ab_col"))) { novo <- guess_ab_col(tbl, "novo", verbose = verbose) } - if (identical(oflo, as.name("guess_ab_col"))) { oflo <- guess_ab_col(tbl, "oflo", verbose = verbose) } - if (identical(oxac, as.name("guess_ab_col"))) { oxac <- guess_ab_col(tbl, "oxac", verbose = verbose) } - if (identical(peni, as.name("guess_ab_col"))) { peni <- guess_ab_col(tbl, "peni", verbose = verbose) } - if (identical(pipe, as.name("guess_ab_col"))) { pipe <- guess_ab_col(tbl, "pipe", verbose = verbose) } - if (identical(pita, as.name("guess_ab_col"))) { pita <- guess_ab_col(tbl, "pita", verbose = verbose) } - if (identical(poly, as.name("guess_ab_col"))) { poly <- guess_ab_col(tbl, "poly", verbose = verbose) } - if (identical(pris, as.name("guess_ab_col"))) { pris <- guess_ab_col(tbl, "pris", verbose = verbose) } - if (identical(qida, as.name("guess_ab_col"))) { qida <- guess_ab_col(tbl, "qida", verbose = verbose) } - if (identical(rifa, as.name("guess_ab_col"))) { rifa <- guess_ab_col(tbl, "rifa", verbose = verbose) } - if (identical(roxi, as.name("guess_ab_col"))) { roxi <- guess_ab_col(tbl, "roxi", verbose = verbose) } - if (identical(siso, as.name("guess_ab_col"))) { siso <- guess_ab_col(tbl, "siso", verbose = verbose) } - if (identical(teic, as.name("guess_ab_col"))) { teic <- guess_ab_col(tbl, "teic", verbose = verbose) } - if (identical(tetr, as.name("guess_ab_col"))) { tetr <- guess_ab_col(tbl, "tetr", verbose = verbose) } - if (identical(tica, as.name("guess_ab_col"))) { tica <- guess_ab_col(tbl, "tica", verbose = verbose) } - if (identical(tige, as.name("guess_ab_col"))) { tige <- guess_ab_col(tbl, "tige", verbose = verbose) } - if (identical(tobr, as.name("guess_ab_col"))) { tobr <- guess_ab_col(tbl, "tobr", verbose = verbose) } - if (identical(trim, as.name("guess_ab_col"))) { trim <- guess_ab_col(tbl, "trim", verbose = verbose) } - if (identical(trsu, as.name("guess_ab_col"))) { trsu <- guess_ab_col(tbl, "trsu", verbose = verbose) } - if (identical(vanc, as.name("guess_ab_col"))) { vanc <- guess_ab_col(tbl, "vanc", verbose = verbose) } + if (identical(amcl, as.name("guess_ab_col"))) { amcl <- guess_ab_col(tbl_, "amcl", verbose = verbose) } + if (identical(amik, as.name("guess_ab_col"))) { amik <- guess_ab_col(tbl_, "amik", verbose = verbose) } + if (identical(amox, as.name("guess_ab_col"))) { amox <- guess_ab_col(tbl_, "amox", verbose = verbose) } + if (identical(ampi, as.name("guess_ab_col"))) { ampi <- guess_ab_col(tbl_, "ampi", verbose = verbose) } + if (identical(azit, as.name("guess_ab_col"))) { azit <- guess_ab_col(tbl_, "azit", verbose = verbose) } + if (identical(azlo, as.name("guess_ab_col"))) { azlo <- guess_ab_col(tbl_, "azlo", verbose = verbose) } + if (identical(aztr, as.name("guess_ab_col"))) { aztr <- guess_ab_col(tbl_, "aztr", verbose = verbose) } + if (identical(cefa, as.name("guess_ab_col"))) { cefa <- guess_ab_col(tbl_, "cefa", verbose = verbose) } + if (identical(cfep, as.name("guess_ab_col"))) { cfep <- guess_ab_col(tbl_, "cfep", verbose = verbose) } + if (identical(cfot, as.name("guess_ab_col"))) { cfot <- guess_ab_col(tbl_, "cfot", verbose = verbose) } + if (identical(cfox, as.name("guess_ab_col"))) { cfox <- guess_ab_col(tbl_, "cfox", verbose = verbose) } + if (identical(cfra, as.name("guess_ab_col"))) { cfra <- guess_ab_col(tbl_, "cfra", verbose = verbose) } + if (identical(cfta, as.name("guess_ab_col"))) { cfta <- guess_ab_col(tbl_, "cfta", verbose = verbose) } + if (identical(cftr, as.name("guess_ab_col"))) { cftr <- guess_ab_col(tbl_, "cftr", verbose = verbose) } + if (identical(cfur, as.name("guess_ab_col"))) { cfur <- guess_ab_col(tbl_, "cfur", verbose = verbose) } + if (identical(chlo, as.name("guess_ab_col"))) { chlo <- guess_ab_col(tbl_, "chlo", verbose = verbose) } + if (identical(cipr, as.name("guess_ab_col"))) { cipr <- guess_ab_col(tbl_, "cipr", verbose = verbose) } + if (identical(clar, as.name("guess_ab_col"))) { clar <- guess_ab_col(tbl_, "clar", verbose = verbose) } + if (identical(clin, as.name("guess_ab_col"))) { clin <- guess_ab_col(tbl_, "clin", verbose = verbose) } + if (identical(clox, as.name("guess_ab_col"))) { clox <- guess_ab_col(tbl_, "clox", verbose = verbose) } + if (identical(coli, as.name("guess_ab_col"))) { coli <- guess_ab_col(tbl_, "coli", verbose = verbose) } + if (identical(czol, as.name("guess_ab_col"))) { czol <- guess_ab_col(tbl_, "czol", verbose = verbose) } + if (identical(dapt, as.name("guess_ab_col"))) { dapt <- guess_ab_col(tbl_, "dapt", verbose = verbose) } + if (identical(doxy, as.name("guess_ab_col"))) { doxy <- guess_ab_col(tbl_, "doxy", verbose = verbose) } + if (identical(erta, as.name("guess_ab_col"))) { erta <- guess_ab_col(tbl_, "erta", verbose = verbose) } + if (identical(eryt, as.name("guess_ab_col"))) { eryt <- guess_ab_col(tbl_, "eryt", verbose = verbose) } + if (identical(fosf, as.name("guess_ab_col"))) { fosf <- guess_ab_col(tbl_, "fosf", verbose = verbose) } + if (identical(fusi, as.name("guess_ab_col"))) { fusi <- guess_ab_col(tbl_, "fusi", verbose = verbose) } + if (identical(gent, as.name("guess_ab_col"))) { gent <- guess_ab_col(tbl_, "gent", verbose = verbose) } + if (identical(imip, as.name("guess_ab_col"))) { imip <- guess_ab_col(tbl_, "imip", verbose = verbose) } + if (identical(kana, as.name("guess_ab_col"))) { kana <- guess_ab_col(tbl_, "kana", verbose = verbose) } + if (identical(levo, as.name("guess_ab_col"))) { levo <- guess_ab_col(tbl_, "levo", verbose = verbose) } + if (identical(linc, as.name("guess_ab_col"))) { linc <- guess_ab_col(tbl_, "linc", verbose = verbose) } + if (identical(line, as.name("guess_ab_col"))) { line <- guess_ab_col(tbl_, "line", verbose = verbose) } + if (identical(mero, as.name("guess_ab_col"))) { mero <- guess_ab_col(tbl_, "mero", verbose = verbose) } + if (identical(mezl, as.name("guess_ab_col"))) { mezl <- guess_ab_col(tbl_, "mezl", verbose = verbose) } + if (identical(mino, as.name("guess_ab_col"))) { mino <- guess_ab_col(tbl_, "mino", verbose = verbose) } + if (identical(moxi, as.name("guess_ab_col"))) { moxi <- guess_ab_col(tbl_, "moxi", verbose = verbose) } + if (identical(nali, as.name("guess_ab_col"))) { nali <- guess_ab_col(tbl_, "nali", verbose = verbose) } + if (identical(neom, as.name("guess_ab_col"))) { neom <- guess_ab_col(tbl_, "neom", verbose = verbose) } + if (identical(neti, as.name("guess_ab_col"))) { neti <- guess_ab_col(tbl_, "neti", verbose = verbose) } + if (identical(nitr, as.name("guess_ab_col"))) { nitr <- guess_ab_col(tbl_, "nitr", verbose = verbose) } + if (identical(norf, as.name("guess_ab_col"))) { norf <- guess_ab_col(tbl_, "norf", verbose = verbose) } + if (identical(novo, as.name("guess_ab_col"))) { novo <- guess_ab_col(tbl_, "novo", verbose = verbose) } + if (identical(oflo, as.name("guess_ab_col"))) { oflo <- guess_ab_col(tbl_, "oflo", verbose = verbose) } + if (identical(oxac, as.name("guess_ab_col"))) { oxac <- guess_ab_col(tbl_, "oxac", verbose = verbose) } + if (identical(peni, as.name("guess_ab_col"))) { peni <- guess_ab_col(tbl_, "peni", verbose = verbose) } + if (identical(pipe, as.name("guess_ab_col"))) { pipe <- guess_ab_col(tbl_, "pipe", verbose = verbose) } + if (identical(pita, as.name("guess_ab_col"))) { pita <- guess_ab_col(tbl_, "pita", verbose = verbose) } + if (identical(poly, as.name("guess_ab_col"))) { poly <- guess_ab_col(tbl_, "poly", verbose = verbose) } + if (identical(pris, as.name("guess_ab_col"))) { pris <- guess_ab_col(tbl_, "pris", verbose = verbose) } + if (identical(qida, as.name("guess_ab_col"))) { qida <- guess_ab_col(tbl_, "qida", verbose = verbose) } + if (identical(rifa, as.name("guess_ab_col"))) { rifa <- guess_ab_col(tbl_, "rifa", verbose = verbose) } + if (identical(roxi, as.name("guess_ab_col"))) { roxi <- guess_ab_col(tbl_, "roxi", verbose = verbose) } + if (identical(siso, as.name("guess_ab_col"))) { siso <- guess_ab_col(tbl_, "siso", verbose = verbose) } + if (identical(teic, as.name("guess_ab_col"))) { teic <- guess_ab_col(tbl_, "teic", verbose = verbose) } + if (identical(tetr, as.name("guess_ab_col"))) { tetr <- guess_ab_col(tbl_, "tetr", verbose = verbose) } + if (identical(tica, as.name("guess_ab_col"))) { tica <- guess_ab_col(tbl_, "tica", verbose = verbose) } + if (identical(tige, as.name("guess_ab_col"))) { tige <- guess_ab_col(tbl_, "tige", verbose = verbose) } + if (identical(tobr, as.name("guess_ab_col"))) { tobr <- guess_ab_col(tbl_, "tobr", verbose = verbose) } + if (identical(trim, as.name("guess_ab_col"))) { trim <- guess_ab_col(tbl_, "trim", verbose = verbose) } + if (identical(trsu, as.name("guess_ab_col"))) { trsu <- guess_ab_col(tbl_, "trsu", verbose = verbose) } + if (identical(vanc, as.name("guess_ab_col"))) { vanc <- guess_ab_col(tbl_, "vanc", verbose = verbose) } col.list <- c(amcl, amik, amox, ampi, azit, azlo, aztr, cefa, cfra, cfep, cfot, cfox, cfta, cftr, cfur, chlo, cipr, clar, clin, clox, coli, czol, dapt, doxy, erta, eryt, fosf, fusi, gent, imip, kana, @@ -348,7 +367,7 @@ eucast_rules <- function(tbl, immediate. = TRUE, call. = FALSE) } - col.list <- check_available_columns(tbl = tbl, col.list = col.list, info = info) + col.list <- check_available_columns(tbl = tbl_, col.list = col.list, info = info) amcl <- col.list[amcl] amik <- col.list[amik] amox <- col.list[amox] @@ -413,22 +432,18 @@ eucast_rules <- function(tbl, trsu <- col.list[trsu] vanc <- col.list[vanc] - number_added_S <- 0 - number_added_I <- 0 - number_added_R <- 0 - number_changed_to_S <- 0 - number_changed_to_I <- 0 - number_changed_to_R <- 0 + ab_missing <- function(ab) { + all(ab %in% c(NULL, NA)) + } - number_affected_rows <- integer(0) verbose_info <- data.frame(row = integer(0), col = character(0), - mo = character(0), mo_fullname = character(0), old = character(0), new = character(0), - rule_source = character(0), + rule = character(0), rule_group = character(0), + rule_name = character(0), stringsAsFactors = FALSE) # helper function for editing the table @@ -454,101 +469,71 @@ eucast_rules <- function(tbl, stop(e, call. = FALSE) } ) - # suppressMessages( - # suppressWarnings( - # tbl[rows, cols] <<- to - # )) + tbl_[rows, cols] <<- tbl_original[rows, cols] after <- as.character(unlist(as.list(tbl_original[rows, cols]))) - tbl[rows, cols] <<- tbl_original[rows, cols] - - number_newly_added_S <- sum(!before %in% c("S", "I", "R") & after == "S", na.rm = TRUE) - number_newly_added_I <- sum(!before %in% c("S", "I", "R") & after == "I", na.rm = TRUE) - number_newly_added_R <- sum(!before %in% c("S", "I", "R") & after == "R", na.rm = TRUE) - number_newly_changed_to_S <- sum(before %in% c("I", "R") & after == "S", na.rm = TRUE) - number_newly_changed_to_I <- sum(before %in% c("S", "R") & after == "I", na.rm = TRUE) - number_newly_changed_to_R <- sum(before %in% c("S", "I") & after == "R", na.rm = TRUE) - - # totals - number_added_S <<- number_added_S + number_newly_added_S - number_added_I <<- number_added_I + number_newly_added_I - number_added_R <<- number_added_R + number_newly_added_R - number_changed_to_S <<- number_changed_to_S + number_newly_changed_to_S - number_changed_to_I <<- number_changed_to_I + number_newly_changed_to_I - number_changed_to_R <<- number_changed_to_R + number_newly_changed_to_R - number_affected_rows <<- unique(c(number_affected_rows, rows)) - - # will be reset at start of every rule - changed_results <<- changed_results + - number_newly_added_S + - number_newly_added_I + - number_newly_added_R + - number_newly_changed_to_S + - number_newly_changed_to_I + - number_newly_changed_to_R - - if (verbose == TRUE) { - old <- as.data.frame(tbl_bak, stringsAsFactors = FALSE)[rows,] - new <- as.data.frame(tbl, stringsAsFactors = FALSE)[rows,] - MOs <- as.data.frame(tbl_original, stringsAsFactors = FALSE)[rows, col_mo][[1]] - for (i in 1:length(cols)) { - verbose_new <- data.frame(row = rows, - col = cols[i], - mo = MOs, - mo_fullname = "", - old = as.character(old[, cols[i]]), - new = as.character(new[, cols[i]]), - rule_source = strip_style(rule[1]), - rule_group = strip_style(rule[2]), - stringsAsFactors = FALSE) - colnames(verbose_new) <- c("row", "col", "mo", "mo_fullname", "old", "new", "rule_source", "rule_group") - verbose_info <<- rbind(verbose_info, verbose_new) - } + # before_df might not be a data.frame, but a tibble of data.table instead + old <- as.data.frame(before_df, stringsAsFactors = FALSE)[rows,] + no_of_changes_this_run <- 0 + for (i in 1:length(cols)) { + verbose_new <- data.frame(row = rows, + col = cols[i], + mo_fullname = tbl_[rows, "fullname"], + old = as.character(old[, cols[i]]), + new = as.character(tbl_[rows, cols[i]]), + rule = strip_style(rule[1]), + rule_group = strip_style(rule[2]), + rule_name = strip_style(rule[3]), + stringsAsFactors = FALSE) + colnames(verbose_new) <- c("row", "col", "mo_fullname", "old", "new", "rule", "rule_group", "rule_name") + verbose_new <- verbose_new %>% filter(old != new | is.na(old)) + verbose_info <<- rbind(verbose_info, verbose_new) + no_of_changes_this_run <- no_of_changes_this_run + nrow(verbose_new) } + # return number of (new) changes + return(no_of_changes_this_run) } - } - - na.rm <- function(col) { - if (is.null(col)) { - "" - } else { - col - } + # return number of (new) changes: none. + return(0) } # save original table - tbl_original <- tbl - tbl_bak <- tbl + tbl_original <- tbl_ # join to microorganisms data set - tbl <- tbl %>% - mutate_at(vars(col_mo), as.mo) %>% - left_join_microorganisms(by = col_mo, suffix = c("_oldcols", "")) %>% - mutate(gramstain = mo_gramstain(pull(., col_mo))) %>% - as.data.frame(stringsAsFactors = FALSE) + suppressWarnings( + tbl_ <- tbl_ %>% + mutate_at(vars(col_mo), as.mo) %>% + left_join_microorganisms(by = col_mo, suffix = c("_oldcols", "")) %>% + mutate(gramstain = mo_gramstain(pull(., col_mo), language = "en"), + genus_species = paste(genus, species)) %>% + as.data.frame(stringsAsFactors = FALSE) + ) if (info == TRUE) { - cat("\nRules by the European Committee on Antimicrobial Susceptibility Testing (EUCAST)\n") + cat(paste0( + "\nRules by the ", bold("European Committee on Antimicrobial Susceptibility Testing (EUCAST)"), + "\n", blue("http://eucast.org/"), "\n")) } # since ampicillin ^= amoxicillin, get the first from the latter (not in original EUCAST table) - if (!is.null(ampi) & !is.null(amox)) { + if (!ab_missing(ampi) & !ab_missing(amox)) { if (verbose == TRUE) { cat("\n VERBOSE: transforming", - length(which(tbl[, amox] == "S" & !tbl[, ampi] %in% c("S", "I", "R"))), + length(which(tbl_[, amox] == "S" & !tbl_[, ampi] %in% c("S", "I", "R"))), "empty ampicillin fields to 'S' based on amoxicillin. ") cat("\n VERBOSE: transforming", - length(which(tbl[, amox] == "I" & !tbl[, ampi] %in% c("S", "I", "R"))), + length(which(tbl_[, amox] == "I" & !tbl_[, ampi] %in% c("S", "I", "R"))), "empty ampicillin fields to 'I' based on amoxicillin. ") cat("\n VERBOSE: transforming", - length(which(tbl[, amox] == "R" & !tbl[, ampi] %in% c("S", "I", "R"))), + length(which(tbl_[, amox] == "R" & !tbl_[, ampi] %in% c("S", "I", "R"))), "empty ampicillin fields to 'R' based on amoxicillin. \n") } - tbl[which(tbl[, amox] == "S" & !tbl[, ampi] %in% c("S", "I", "R")), ampi] <- "S" - tbl[which(tbl[, amox] == "I" & !tbl[, ampi] %in% c("S", "I", "R")), ampi] <- "I" - tbl[which(tbl[, amox] == "R" & !tbl[, ampi] %in% c("S", "I", "R")), ampi] <- "R" - } else if (is.null(ampi) & !is.null(amox)) { + tbl_[which(tbl_[, amox] == "S" & !tbl_[, ampi] %in% c("S", "I", "R")), ampi] <- "S" + tbl_[which(tbl_[, amox] == "I" & !tbl_[, ampi] %in% c("S", "I", "R")), ampi] <- "I" + tbl_[which(tbl_[, amox] == "R" & !tbl_[, ampi] %in% c("S", "I", "R")), ampi] <- "R" + } else if (ab_missing(ampi) & !ab_missing(amox)) { # ampicillin column is missing, but amoxicillin is available message(blue(paste0("NOTE: Using column `", bold(amox), "` as input for ampicillin (J01CA01) since many EUCAST rules depend on it."))) ampi <- amox @@ -562,1357 +547,283 @@ eucast_rules <- function(tbl, glycopeptides <- c(vanc, teic) streptogramins <- c(qida, pris) # should officially also be quinupristin/dalfopristin cephalosporins <- c(cfep, cfot, cfox, cfra, cfta, cftr, cfur, czol) + cephalosporins_without_cfta <- cephalosporins[cephalosporins != ifelse(is.null(cfta), "", cfta)] carbapenems <- c(erta, imip, mero) aminopenicillins <- c(ampi, amox) ureidopenicillins <- c(pipe, pita, azlo, mezl) fluoroquinolones <- c(oflo, cipr, norf, levo, moxi) - all_betalactam <- c(aminopenicillins, ureidopenicillins, cephalosporins, carbapenems, amcl, oxac, clox, peni) + all_betalactams <- c(aminopenicillins, ureidopenicillins, cephalosporins, carbapenems, amcl, oxac, clox, peni) - if (any(c("all", "breakpoints") %in% rules)) { - # BREAKPOINTS ------------------------------------------------------------- - - if (info == TRUE) { - cat(bold(paste0('\nEUCAST Clinical Breakpoints (v', EUCAST_VERSION_BREAKPOINTS, ')\n'))) + # Help function to get available antibiotic column names ------------------ + get_antibiotic_columns <- function(x, df) { + x <- trimws(unlist(strsplit(x, ",", fixed = TRUE))) + y <- character(0) + for (i in 1:length(x)) { + y <- c(y, tryCatch(get(x[i]), error = function(e) "")) } - rule_group <- "Breakpoints" + y[y != "" & y %in% colnames(df)] + } - # Enterobacteriales (Order) ---- - rule <- 'Enterobacteriales (Order)' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) + eucast_rules_df <- eucast_rules_file() + no_of_changes <- 0 + for (i in 1:nrow(eucast_rules_df)) { + + rule_previous <- eucast_rules_df[max(1, i - 1), "reference.rule"] + rule_current <- eucast_rules_df[i, "reference.rule"] + rule_next <- eucast_rules_df[min(nrow(eucast_rules_df), i + 1), "reference.rule"] + rule_group_previous <- eucast_rules_df[max(1, i - 1), "reference.rule_group"] + rule_group_current <- eucast_rules_df[i, "reference.rule_group"] + rule_group_next <- eucast_rules_df[min(nrow(eucast_rules_df), i + 1), "reference.rule_group"] + #no_of_changes <- 0 + if (is.na(eucast_rules_df[i, 4])) { + rule_text <- paste(eucast_rules_df[i, 6], "=", eucast_rules_df[i, 7]) + } else { + rule_text <- paste("if", eucast_rules_df[i, 4], "=", eucast_rules_df[i, 5], + "then", eucast_rules_df[i, 6], "=", eucast_rules_df[i, 7]) + } + if (i == 1) { + rule_previous <- "" + rule_group_previous <- "" + } + if (i == nrow(eucast_rules_df)) { + rule_next <- "" + rule_group_next <- "" } - if (!is.null(ampi)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$order == 'Enterobacteriales' - & tbl[, ampi] == 'S'), - cols = amox) + # don't apply rules if user doesn't want to apply them + if (rule_group_current %like% "breakpoint" & !any(c("all", "breakpoints") %in% rules)) { + next } - if (!is.null(ampi)) { - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$order == 'Enterobacteriales' - & tbl[, ampi] == 'I'), - cols = amox) + if (rule_group_current %like% "expert" & !any(c("all", "expert") %in% rules)) { + next } - if (!is.null(ampi)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$order == 'Enterobacteriales' - & tbl[, ampi] == 'R'), - cols = amox) - } - if (info == TRUE) { - txt_ok() - } - # Staphylococcus ---- - rule <- italic('Staphylococcus') - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(peni) & !is.null(cfox)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, peni] == 'S' - & tbl[, cfox] == 'S'), - cols = c(ampi, amox, pipe, tica)) - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, peni] == 'R' - & tbl[, cfox] == 'S'), - cols = c(oxac, clox)) - } - if (!is.null(cfox)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, cfox] == 'R'), - cols = all_betalactam) - } - if (!is.null(ampi)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Staphylococcus saprophyticus" - & tbl[, ampi] == 'S'), - cols = c(amox, amcl, pipe, pita)) - } - if (!is.null(cfox)) { - # inferred from cefoxitin - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, cfox] == 'S'), - cols = c(carbapenems, cephalosporins[cephalosporins != na.rm(cfta)])) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, cfox] == 'I'), - cols = c(carbapenems, cephalosporins[cephalosporins != na.rm(cfta)])) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, cfox] == 'R'), - cols = c(carbapenems, cephalosporins[cephalosporins != na.rm(cfta)])) - } - if (!is.null(norf)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, norf] == 'S'), - cols = c(cipr, levo, moxi, oflo)) - } - if (!is.null(eryt)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, eryt] == 'S'), - cols = c(azit, clar, roxi)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, eryt] == 'I'), - cols = c(azit, clar, roxi)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, eryt] == 'R'), - cols = c(azit, clar, roxi)) - } - if (!is.null(tetr)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Staphylococcus" - & tbl[, tetr] == 'S'), - cols = c(doxy, mino)) - } - if (info == TRUE) { - txt_ok() - } - # Enterococcus ---- - rule <- italic('Enterococcus') - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(ampi)) { # penicillin group - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Enterococcus faecium" - & tbl[, ampi] == 'R'), - cols = all_betalactam) - } - if (!is.null(ampi)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Enterococcus" - & tbl[, ampi] == 'S'), - cols = c(amox, amcl, pipe, pita)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Enterococcus" - & tbl[, ampi] == 'I'), - cols = c(amox, amcl, pipe, pita)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Enterococcus" - & tbl[, ampi] == 'R'), - cols = c(amox, amcl, pipe, pita)) - } - if (!is.null(norf)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Enterococcus" - & tbl[, norf] == 'S'), - cols = c(cipr, levo)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Enterococcus" - & tbl[, norf] == 'I'), - cols = c(cipr, levo)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Enterococcus" - & tbl[, norf] == 'R'), - cols = c(cipr, levo)) - } - if (info == TRUE) { - txt_ok() - } - # Streptococcus groups A, B, C, G---- - rule <- paste(italic('Streptococcus'), 'groups A, B, C, G') - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(peni)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus (pyogenes|agalactiae|dysgalactiae|group A|group B|group C|group G)" - & tbl[, peni] == 'S'), - cols = c(aminopenicillins, ureidopenicillins, cephalosporins, carbapenems, clox, amcl)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus (pyogenes|agalactiae|dysgalactiae|group A|group B|group C|group G)" - & tbl[, peni] == 'I'), - cols = c(aminopenicillins, ureidopenicillins, cephalosporins, carbapenems, clox, amcl)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus (pyogenes|agalactiae|dysgalactiae|group A|group B|group C|group G)" - & tbl[, peni] == 'R'), - cols = c(aminopenicillins, ureidopenicillins, cephalosporins, carbapenems, clox, amcl)) - } - if (!is.null(norf)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus (pyogenes|agalactiae|dysgalactiae|group A|group B|group C|group G)" - & tbl[, norf] == 'S'), - cols = c(levo, moxi)) - } - if (!is.null(eryt)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus (pyogenes|agalactiae|dysgalactiae|group A|group B|group C|group G)" - & tbl[, eryt] == 'S'), - cols = c(azit, clar, roxi)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus (pyogenes|agalactiae|dysgalactiae|group A|group B|group C|group G)" - & tbl[, eryt] == 'I'), - cols = c(azit, clar, roxi)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus (pyogenes|agalactiae|dysgalactiae|group A|group B|group C|group G)" - & tbl[, eryt] == 'R'), - cols = c(azit, clar, roxi)) - } - if (!is.null(tetr)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus (pyogenes|agalactiae|dysgalactiae|group A|group B|group C|group G)" - & tbl[, tetr] == 'S'), - cols = c(doxy, mino)) - } - if (info == TRUE) { - txt_ok() - } - # Streptococcus pneumoniae ---- - rule <- italic('Streptococcus pneumoniae') - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(peni)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus pneumoniae" - & tbl[, peni] == 'S'), - cols = c(ampi, amox, amcl, pipe, pita)) - } - if (!is.null(ampi)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus pneumoniae" - & tbl[, ampi] == 'S'), - cols = c(amox, amcl, pipe, pita)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus pneumoniae" - & tbl[, ampi] == 'I'), - cols = c(amox, amcl, pipe, pita)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus pneumoniae" - & tbl[, ampi] == 'R'), - cols = c(amox, amcl, pipe, pita)) - } - if (!is.null(norf)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus pneumoniae" - & tbl[, norf] == 'S'), - cols = c(levo, moxi)) - } - if (!is.null(eryt)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus pneumoniae" - & tbl[, eryt] == 'S'), - cols = c(azit, clar, roxi)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus pneumoniae" - & tbl[, eryt] == 'I'), - cols = c(azit, clar, roxi)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus pneumoniae" - & tbl[, eryt] == 'R'), - cols = c(azit, clar, roxi)) - } - if (!is.null(tetr)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Streptococcus pneumoniae" - & tbl[, tetr] == 'S'), - cols = c(doxy, mino)) - } - if (info == TRUE) { - txt_ok() - } - # Viridans group streptococci ---- - rule <- 'Viridans group streptococci' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - viridans_group <- c("anginosus", "australis", "bovis", "constellatus", "cristatus", - "equinus", "gallolyticus", "gordonii", "infantarius", "infantis", - "intermedius", "mitis", "mutans", "oligofermentans", "oralis", - "parasanguinis", "peroris", "pseudopneumoniae", "salivarius", - "sanguinis", "sinensis", "sobrinus", "thermophilus", "vestibularis") - if (!is.null(peni)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Streptococcus" & tbl$species %in% viridans_group - & tbl[, peni] == 'S'), - cols = c(ampi, amox, amcl, pipe, pita)) - } - if (!is.null(ampi)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Streptococcus" & tbl$species %in% viridans_group - & tbl[, ampi] == 'S'), - cols = c(amox, amcl, pipe, pita)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Streptococcus" & tbl$species %in% viridans_group - & tbl[, ampi] == 'I'), - cols = c(amox, amcl, pipe, pita)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == "Streptococcus" & tbl$species %in% viridans_group - & tbl[, ampi] == 'R'), - cols = c(amox, amcl, pipe, pita)) - } - if (info == TRUE) { - txt_ok() - } - # Haemophilus influenzae ---- - rule <- italic('Haemophilus influenzae') - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(ampi)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Haemophilus influenzae" - & tbl[, ampi] == 'S'), - cols = c(amox, pipe)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Haemophilus influenzae" - & tbl[, ampi] == 'I'), - cols = c(amox, pipe)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Haemophilus influenzae" - & tbl[, ampi] == 'R'), - cols = c(amox, pipe)) - } - if (!is.null(peni)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Haemophilus influenzae" - & tbl[, peni] == 'S'), - cols = c(ampi, amox, amcl, pipe, pita)) - } - if (!is.null(amcl)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Haemophilus influenzae" - & tbl[, amcl] == 'S'), - cols = pita) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Haemophilus influenzae" - & tbl[, amcl] == 'I'), - cols = pita) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Haemophilus influenzae" - & tbl[, amcl] == 'R'), - cols = pita) - } - if (!is.null(nali)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Haemophilus influenzae" - & tbl[, nali] == 'S'), - cols = c(cipr, levo, moxi, oflo)) - } - if (!is.null(tetr)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Haemophilus influenzae" - & tbl[, tetr] == 'S'), - cols = c(doxy, mino)) - } - if (info == TRUE) { - txt_ok() - } - # Moraxella catarrhalis ---- - rule <- italic('Moraxella catarrhalis') - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(amcl)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Moraxella catarrhalis" - & tbl[, amcl] == 'S'), - cols = pita) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Moraxella catarrhalis" - & tbl[, amcl] == 'I'), - cols = pita) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Moraxella catarrhalis" - & tbl[, amcl] == 'R'), - cols = pita) - } - if (!is.null(nali)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Moraxella catarrhalis" - & tbl[, nali] == 'S'), - cols = c(cipr, levo, moxi, oflo)) - } - if (!is.null(eryt)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Moraxella catarrhalis" - & tbl[, eryt] == 'S'), - cols = c(azit, clar, roxi)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Moraxella catarrhalis" - & tbl[, eryt] == 'I'), - cols = c(azit, clar, roxi)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Moraxella catarrhalis" - & tbl[, eryt] == 'R'), - cols = c(azit, clar, roxi)) - } - if (!is.null(tetr)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Moraxella catarrhalis" - & tbl[, tetr] == 'S'), - cols = c(doxy, mino)) - } - if (info == TRUE) { - txt_ok() - } - # Anaerobic Gram positives ---- - rule <- 'Anaerobic Gram positives' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(peni)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus %in% c("Clostridium", "Actinomyces", "Propionibacterium", - "Cutibacterium", # new name of Propionibacterium - "Bifidobacterium", "Eggerthella", "Eubacterium", - "Lactobacillus ", "Actinomyces") - & tbl[, peni] == 'S'), - cols = c(ampi, amox, pipe, pita, tica)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$genus %in% c("Clostridium", "Actinomyces", "Propionibacterium", - "Cutibacterium", # new name of Propionibacterium - "Bifidobacterium", "Eggerthella", "Eubacterium", - "Lactobacillus ", "Actinomyces") - & tbl[, peni] == 'I'), - cols = c(ampi, amox, pipe, pita, tica)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus %in% c("Clostridium", "Actinomyces", "Propionibacterium", - "Cutibacterium", # new name of Propionibacterium - "Bifidobacterium", "Eggerthella", "Eubacterium", - "Lactobacillus ", "Actinomyces") - & tbl[, peni] == 'R'), - cols = c(ampi, amox, pipe, pita, tica)) - } - if (info == TRUE) { - txt_ok() - } - # Anaerobic Gram negatives ---- - rule <- 'Anaerobic Gram negatives' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(peni)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$genus %in% c("Bacteroides", "Prevotella", "Porphyromonas", - "Fusobacterium", "Bilophila ", "Mobiluncus") - & tbl[, peni] == 'S'), - cols = c(ampi, amox, pipe, pita, tica)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$genus %in% c("Bacteroides", "Prevotella", "Porphyromonas", - "Fusobacterium", "Bilophila ", "Mobiluncus") - & tbl[, peni] == 'I'), - cols = c(ampi, amox, pipe, pita, tica)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus %in% c("Bacteroides", "Prevotella", "Porphyromonas", - "Fusobacterium", "Bilophila ", "Mobiluncus") - & tbl[, peni] == 'R'), - cols = c(ampi, amox, pipe, pita, tica)) - } - if (info == TRUE) { - txt_ok() - } - # Pasteurella multocida ---- - rule <- italic('Pasteurella multocida') - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(peni)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Pasteurella multocida" - & tbl[, peni] == 'S'), - cols = c(ampi, amox)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Pasteurella multocida" - & tbl[, peni] == 'I'), - cols = c(ampi, amox)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Pasteurella multocida" - & tbl[, peni] == 'R'), - cols = c(ampi, amox)) - } - if (info == TRUE) { - txt_ok() - } - # Campylobacter jejuni and coli ---- - rule <- paste(italic('Campylobacter jejuni'), 'and', italic('C. coli')) - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(eryt)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Campylobacter (jejuni|coli)" - & tbl[, eryt] == 'S'), - cols = c(azit, clar)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Campylobacter (jejuni|coli)" - & tbl[, eryt] == 'I'), - cols = c(azit, clar)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Campylobacter (jejuni|coli)" - & tbl[, eryt] == 'R'), - cols = c(azit, clar)) - } - if (!is.null(tetr)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Campylobacter (jejuni|coli)" - & tbl[, tetr] == 'S'), - cols = doxy) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Campylobacter (jejuni|coli)" - & tbl[, tetr] == 'I'), - cols = doxy) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Campylobacter (jejuni|coli)" - & tbl[, tetr] == 'R'), - cols = doxy) - } - if (info == TRUE) { - txt_ok() - } - # Aerococcus sanguinicola/urinae ---- - rule <- paste(italic('Aerococcus sanguinicola'), 'and', italic('A. urinae')) - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(norf)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Aerococcus (sanguinicola|urinae)" - & tbl[, norf] == 'S'), - cols = fluoroquinolones) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Aerococcus (sanguinicola|urinae)" - & tbl[, norf] == 'I'), - cols = fluoroquinolones) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Aerococcus (sanguinicola|urinae)" - & tbl[, norf] == 'R'), - cols = fluoroquinolones) - } - if (!is.null(cipr)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Aerococcus (sanguinicola|urinae)" - & tbl[, cipr] == 'S'), - cols = levo) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Aerococcus (sanguinicola|urinae)" - & tbl[, cipr] == 'I'), - cols = levo) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Aerococcus (sanguinicola|urinae)" - & tbl[, cipr] == 'R'), - cols = levo) - } - if (info == TRUE) { - txt_ok() - } - # Kingella kingae ---- - rule <- italic('Kingella kingae') - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(peni)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Kingella kingae" - & tbl[, peni] == 'S'), - cols = c(ampi, amox)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Kingella kingae" - & tbl[, peni] == 'I'), - cols = c(ampi, amox)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Kingella kingae" - & tbl[, peni] == 'R'), - cols = c(ampi, amox)) - } - if (!is.null(eryt)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Kingella kingae" - & tbl[, eryt] == 'S'), - cols = c(azit, clar)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Kingella kingae" - & tbl[, eryt] == 'I'), - cols = c(azit, clar)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Kingella kingae" - & tbl[, eryt] == 'R'), - cols = c(azit, clar)) - } - if (!is.null(tetr)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% "^Kingella kingae" - & tbl[, tetr] == 'S'), - cols = doxy) - } - if (info == TRUE) { - txt_ok() - } - - } # end of breakpoints - if (any(c("all", "expert") %in% rules)) { - - # EXPERT RULES AND INTRINSIC RESISTANCE ----------------------------------- - - if (info == TRUE) { - cat(bold(paste0('\nEUCAST Expert Rules, Intrinsic Resistance and Exceptional Phenotypes (v', EUCAST_VERSION_EXPERT_RULES, ')\n'))) - } - rule_group <- "Expert Rules" - - # Table 1: Intrinsic resistance in Enterobacteriaceae ---- - rule <- paste('Table 1: Intrinsic resistance in', italic('Enterobacteriaceae')) - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # Intrinsic R for this group - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$family == 'Enterobacteriaceae'), - cols = c(peni, glycopeptides, fusi, macrolides, linc, streptogramins, rifa, dapt, line)) - # Citrobacter - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Citrobacter (koseri|amalonaticus|sedlakii|farmeri|rodentium)'), - cols = c(aminopenicillins, tica)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Citrobacter (freundii|braakii|murliniae|werkmanii|youngae)'), - cols = c(aminopenicillins, amcl, czol, cfox)) - # Enterobacter - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Enterobacter cloacae'), - cols = c(aminopenicillins, amcl, czol, cfox)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Enterobacter aerogenes'), - cols = c(aminopenicillins, amcl, czol, cfox)) - # Escherichia - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Escherichia hermanni'), - cols = c(aminopenicillins, tica)) - # Hafnia - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Hafnia alvei'), - cols = c(aminopenicillins, amcl, czol, cfox)) - # Klebsiella - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Klebsiella'), - cols = c(aminopenicillins, tica)) - # Morganella / Proteus - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Morganella morganii'), - cols = c(aminopenicillins, amcl, czol, tetracyclines, polymyxins, nitr)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Proteus mirabilis'), - cols = c(tetracyclines, tige, polymyxins, nitr)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Proteus penneri'), - cols = c(aminopenicillins, czol, cfur, tetracyclines, tige, polymyxins, nitr)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Proteus vulgaris'), - cols = c(aminopenicillins, czol, cfur, tetracyclines, tige, polymyxins, nitr)) - # Providencia - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Providencia rettgeri'), - cols = c(aminopenicillins, amcl, czol, cfur, tetracyclines, tige, polymyxins, nitr)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Providencia stuartii'), - cols = c(aminopenicillins, amcl, czol, cfur, tetracyclines, tige, polymyxins, nitr)) - # Raoultella - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Raoultella'), - cols = c(aminopenicillins, tica)) - # Serratia - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Serratia marcescens'), - cols = c(aminopenicillins, amcl, czol, cfox, cfur, tetracyclines[tetracyclines != na.rm(mino)], polymyxins, nitr)) - # Yersinia - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Yersinia enterocolitica'), - cols = c(aminopenicillins, amcl, tica, czol, cfox)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Yersinia pseudotuberculosis'), - cols = c(poly, coli)) - if (info == TRUE) { - txt_ok() - } - - # Table 2: Intrinsic resistance in non-fermentative Gram-negative bacteria ---- - rule <- 'Table 2: Intrinsic resistance in non-fermentative Gram-negative bacteria' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # Intrinsic R for this group - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus %in% c('Achromobacter', - 'Acinetobacter', - 'Alcaligenes', - 'Bordatella', - 'Burkholderia', - 'Elizabethkingia', - 'Flavobacterium', - 'Ochrobactrum', - 'Pseudomonas', - 'Stenotrophomonas')), - cols = c(peni, cfox, cfur, glycopeptides, fusi, macrolides, linc, streptogramins, rifa, dapt, line)) - # Acinetobacter - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Acinetobacter (baumannii|pittii|nosocomialis|calcoaceticus)'), - cols = c(aminopenicillins, amcl, czol, cfot, cftr, aztr, erta, trim, fosf, tetracyclines[tetracyclines != na.rm(mino)])) - # Achromobacter - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Achromobacter (xylosoxydans|xylosoxidans)'), - cols = c(aminopenicillins, czol, cfot, cftr, erta)) - # Burkholderia - edit_rsi(to = 'R', - rule = c(rule_group, rule), - # the 'Burkholderia cepacia complex' are all these species: (PMID 16217180) - rows = which(tbl$fullname %like% '^Burkholderia (cepacia|multivorans|cenocepacia|stabilis|vietnamiensis|dolosa|ambifaria|anthina|pyrrocinia|ubonensis)'), - cols = c(aminopenicillins, amcl, tica, pipe, pita, czol, cfot, cftr, aztr, erta, cipr, chlo, aminoglycosides, trim, fosf, polymyxins)) - # Elizabethkingia - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Elizabethkingia meningoseptic(a|um)'), - cols = c(aminopenicillins, amcl, tica, czol, cfot, cftr, cfta, cfep, aztr, erta, imip, mero, polymyxins)) - # Ochrobactrum - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Ochrobactrum anthropi'), - cols = c(aminopenicillins, amcl, tica, pipe, pita, czol, cfot, cftr, cfta, cfep, aztr, erta)) - # Pseudomonas - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Pseudomonas aeruginosa'), - cols = c(aminopenicillins, amcl, czol, cfot, cftr, erta, chlo, kana, neom, trim, trsu, tetracyclines, tige)) - # Stenotrophomonas - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Stenotrophomonas maltophilia'), - cols = c(aminopenicillins, amcl, tica, pipe, pita, czol, cfot, cftr, cfta, aztr, erta, imip, mero, aminoglycosides, trim, fosf, tetr)) - if (info == TRUE) { - txt_ok() - } - - # Table 3: Intrinsic resistance in other Gram-negative bacteria ---- - rule <- 'Table 3: Intrinsic resistance in other Gram-negative bacteria' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # Intrinsic R for this group - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus %in% c('Haemophilus', - 'Moraxella', - 'Neisseria', - 'Campylobacter')), - cols = c(glycopeptides, linc, dapt, line)) - # Haemophilus - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Haemophilus influenzae'), - cols = c(fusi, streptogramins)) - # Moraxella - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Moraxella catarrhalis'), - cols = trim) - # Neisseria - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == 'Neisseria'), - cols = trim) - # Campylobacter - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Campylobacter fetus'), - cols = c(fusi, streptogramins, trim, nali)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Campylobacter (jejuni|coli)'), - cols = c(fusi, streptogramins, trim)) - if (info == TRUE) { - txt_ok() - } - - # Table 4: Intrinsic resistance in Gram-positive bacteria ---- - rule <- 'Table 4: Intrinsic resistance in Gram-positive bacteria' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # Intrinsic R for this group - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$gramstain == "Gram positive"), - cols = c(aztr, polymyxins, nali)) - # Staphylococcus - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Staphylococcus saprophyticus'), - cols = c(fusi, cfta, fosf, novo)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Staphylococcus (cohnii|xylosus)'), - cols = c(cfta, novo)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Staphylococcus capitis'), - cols = c(cfta, fosf)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Staphylococcus (aureus|epidermidis|coagulase negatief|hominis|haemolyticus|intermedius|pseudointermedius)'), - cols = cfta) - # Streptococcus - # rule 4.5 - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == 'Streptococcus'), - cols = c(fusi, aminoglycosides)) - # Enterococcus - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Enterococcus faecalis'), - cols = c(fusi, cfta, cephalosporins[cephalosporins != na.rm(cfta)], aminoglycosides, macrolides, clin, qida, trim, trsu)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Enterococcus (gallinarum|casseliflavus)'), - cols = c(fusi, cfta, cephalosporins[cephalosporins != na.rm(cfta)], aminoglycosides, macrolides, clin, qida, vanc, trim, trsu)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Enterococcus faecium'), - cols = c(fusi, cfta, cephalosporins[cephalosporins != na.rm(cfta)], aminoglycosides, macrolides, trim, trsu)) - # Corynebacterium - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == 'Corynebacterium'), - cols = fosf) - # Listeria - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Listeria monocytogenes'), - cols = c(cfta, cephalosporins[cephalosporins != na.rm(cfta)])) - # other - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus %in% c('Leuconostoc', 'Pediococcus')), - cols = glycopeptides) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == 'Lactobacillus'), - cols = glycopeptides) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Clostridium (ramosum|innocuum)'), - cols = vanc) - if (info == TRUE) { - txt_ok() - } - - # Table 8: Interpretive rules for B-lactam agents and Gram-positive cocci ---- - rule <- 'Table 8: Interpretive rules for B-lactam agents and Gram-positive cocci' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # rule 8.3 - if (!is.null(peni)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Streptococcus (pyogenes|agalactiae|dysgalactiae|group A|group B|group C|group G)' - & tbl[, peni] == 'S'), - cols = c(aminopenicillins, cephalosporins, carbapenems)) - } - # rule 8.6 - if (!is.null(ampi)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == 'Enterococcus' - & tbl[, ampi] == 'R'), - cols = c(ureidopenicillins, carbapenems)) - } - if (!is.null(amox)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == 'Enterococcus' - & tbl[, amox] == 'R'), - cols = c(ureidopenicillins, carbapenems)) - } - if (info == TRUE) { - txt_ok() - } - - # Table 9: Interpretive rules for B-lactam agents and Gram-negative rods ---- - rule <- 'Table 9: Interpretive rules for B-lactam agents and Gram-negative rods' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # rule 9.3 - if (!is.null(tica) & !is.null(pipe)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$family == 'Enterobacteriaceae' - & tbl[, tica] == 'R' - & tbl[, pipe] == 'S'), - cols = pipe) - } - if (info == TRUE) { - txt_ok() - } - - # Table 10: Interpretive rules for B-lactam agents and other Gram-negative bacteria ---- - rule <- 'Table 10: Interpretive rules for B-lactam agents and other Gram-negative bacteria' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # rule 10.2 - # if (!is.null(ampi)) { - # you should know first if the are B-lactamase positive, so do not run for now - # edit_rsi(to = 'R', - # rule = c(rule_group, rule), - # rows = which(tbl$fullname %like% '^Haemophilus influenza' - # & tbl[, ampi] == 'R'), - # cols = c(ampi, amox, amcl, pipe, pita, cfur)) - # } - if (info == TRUE) { - txt_ok() - } - - # Table 11: Interpretive rules for macrolides, lincosamides, and streptogramins ---- - rule <- 'Table 11: Interpretive rules for macrolides, lincosamides, and streptogramins' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # rule 11.1 - if (!is.null(eryt)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl[, eryt] == 'S'), - cols = c(azit, clar)) - edit_rsi(to = 'I', - rule = c(rule_group, rule), - rows = which(tbl[, eryt] == 'I'), - cols = c(azit, clar)) - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl[, eryt] == 'R'), - cols = c(azit, clar)) - } - if (info == TRUE) { - txt_ok() - } - - # Table 12: Interpretive rules for aminoglycosides ---- - rule <- 'Table 12: Interpretive rules for aminoglycosides' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # rule 12.2 - if (!is.null(tobr)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == 'Staphylococcus' - & tbl[, tobr] == 'R'), - cols = c(kana, amik)) - } - # rule 12.3 - if (!is.null(gent)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == 'Staphylococcus' - & tbl[, gent] == 'R'), - cols = aminoglycosides) - } - # rule 12.8 - if (!is.null(gent) & !is.null(tobr)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$family == 'Enterobacteriaceae' - & tbl[, gent] == 'I' - & tbl[, tobr] == 'S'), - cols = gent) - } - # rule 12.9 - if (!is.null(gent) & !is.null(tobr)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$family == 'Enterobacteriaceae' - & tbl[, tobr] == 'I' - & tbl[, gent] == 'R'), - cols = tobr) - } - if (info == TRUE) { - txt_ok() + if (rule_group_current %like% "other" & !any(c("all", "other") %in% rules)) { + next } - # Table 13: Interpretive rules for quinolones ---- - rule <- 'Table 13: Interpretive rules for quinolones' if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - # rule 13.2 - if (!is.null(moxi)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$genus == 'Staphylococcus' - & tbl[, moxi] == 'R'), - cols = fluoroquinolones) - } - # rule 13.4 - if (!is.null(moxi)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Streptococcus pneumoniae' - & tbl[, moxi] == 'R'), - cols = fluoroquinolones) - } - # rule 13.5 - if (!is.null(cipr)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$family == 'Enterobacteriaceae' - & tbl[, cipr] == 'R'), - cols = fluoroquinolones) - } - # rule 13.8 - if (!is.null(cipr)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl$fullname %like% '^Neisseria gonorrhoeae' - & tbl[, cipr] == 'R'), - cols = fluoroquinolones) - } - if (info == TRUE) { - txt_ok() + # Print rule (group) ------------------------------------------------------ + if (rule_group_current != rule_group_previous) { + # is new rule group, one of Breakpoints, Expert Rules and Other + cat(bold( + case_when( + rule_group_current %like% "breakpoint" ~ + paste0("\nEUCAST Clinical Breakpoints (v", EUCAST_VERSION_BREAKPOINTS, ")\n"), + rule_group_current %like% "expert" ~ + paste0("\nEUCAST Expert Rules, Intrinsic Resistance and Exceptional Phenotypes (v", EUCAST_VERSION_EXPERT_RULES, ")\n"), + TRUE ~ + "\nOther rules\n" + ) + )) + } + # Print rule ------------------------------------------------------------- + if (rule_current != rule_previous) { + # is new rule within group, print its name + if (rule_current %in% c(AMR::microorganisms$family, + AMR::microorganisms$fullname)) { + cat(italic(rule_current)) + } else { + cat(rule_current) + } + warned <- FALSE + } } - } # end of expert rules - if (any(c("all", "other") %in% rules)) { + # Get rule from file ------------------------------------------------------ + col_mo_property <- eucast_rules_df[i, 1] + like_is_one_of <- eucast_rules_df[i, 2] - # OTHER RULES ------------------------------------------------------------- - - if (info == TRUE) { - cat(bold('\nOther rules\n')) - } - rule_group <- "Other rules" - - rule <- 'Non-EUCAST: ampicillin = R where amoxicillin/clav acid = R' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(amcl)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl[, amcl] == 'R'), - cols = ampi) - } - if (info == TRUE) { - txt_ok() - } - rule <- 'Non-EUCAST: piperacillin = R where piperacillin/tazobactam = R' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(pita)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl[, pita] == 'R'), - cols = pipe) - } - if (info == TRUE) { - txt_ok() - } - rule <- 'Non-EUCAST: trimethoprim = R where trimethoprim/sulfa = R' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(trsu)) { - edit_rsi(to = 'R', - rule = c(rule_group, rule), - rows = which(tbl[, trsu] == 'R'), - cols = trim) - } - if (info == TRUE) { - txt_ok() - } - rule <- 'Non-EUCAST: amoxicillin/clav acid = S where ampicillin = S' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(ampi)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl[, ampi] == 'S'), - cols = amcl) - } - if (info == TRUE) { - txt_ok() - } - rule <- 'Non-EUCAST: piperacillin/tazobactam = S where piperacillin = S' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(pipe)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl[, pipe] == 'S'), - cols = pita) - } - if (info == TRUE) { - txt_ok() - } - rule <- 'Non-EUCAST: trimethoprim/sulfa = S where trimethoprim = S' - if (info == TRUE) { - warned <- FALSE - changed_results <- 0 - cat(rule) - } - if (!is.null(trim)) { - edit_rsi(to = 'S', - rule = c(rule_group, rule), - rows = which(tbl[, trim] == 'S'), - cols = trsu) - } - if (info == TRUE) { - txt_ok() + # be sure to comprise all coagulase-negative/-positive Staphylococci when they are mentioned + if (eucast_rules_df[i, 3] %like% "coagulase-") { + suppressWarnings( + all_staph <- AMR::microorganisms %>% + filter(genus == "Staphylococcus") %>% + mutate(CNS_CPS = mo_fullname(mo, Becker = "all")) + ) + if (eucast_rules_df[i, 3] %like% "coagulase-") { + eucast_rules_df[i, 3] <- paste0("^(", + paste0(all_staph %>% + filter(CNS_CPS %like% "coagulase-negative") %>% + pull(fullname), + collapse = "|"), + ")$") + } else { + eucast_rules_df[i, 3] <- paste0("^(", + paste0(all_staph %>% + filter(CNS_CPS %like% "coagulase-positive") %>% + pull(fullname), + collapse = "|"), + ")$") + } + like_is_one_of <- "like" } - } # end of other rules + if (like_is_one_of == "is") { + mo_value <- paste0("^", eucast_rules_df[i, 3], "$") + } else if (like_is_one_of == "one_of") { + # "Clostridium, Actinomyces, ..." -> "^(Clostridium|Actinomyces|...)$" + mo_value <- paste0("^(", + paste(trimws(unlist(strsplit(eucast_rules_df[i, 3], ",", fixed = TRUE))), + collapse = "|"), + ")$") + } else if (like_is_one_of == "like") { + mo_value <- eucast_rules_df[i, 3] + } else { + stop("invalid like_is_one_of", call. = FALSE) + } - # restore old col_mo values if needed - # if (!is.null(col_mo_original)) { - # tbl_original[, col_mo] <- col_mo_original - # } + source_antibiotics <- eucast_rules_df[i, 4] + source_value <- trimws(unlist(strsplit(eucast_rules_df[i, 5], ",", fixed = TRUE))) + target_antibiotics <- eucast_rules_df[i, 6] + target_value <- eucast_rules_df[i, 7] + if (is.na(source_antibiotics)) { + rows <- tryCatch(which(tbl_[, col_mo_property] %like% mo_value), + error = function(e) integer(0)) + } else { + source_antibiotics <- get_antibiotic_columns(source_antibiotics, tbl_) + if (length(source_value) == 1 & length(source_antibiotics) > 1) { + source_value <- rep(source_value, length(source_antibiotics)) + } + if (length(source_antibiotics) == 0) { + rows <- integer(0) + } else if (length(source_antibiotics) == 1) { + rows <- tryCatch(which(tbl_[, col_mo_property] %like% mo_value + & tbl_[, source_antibiotics[1L]] == source_value[1L]), + error = function(e) integer(0)) + } else if (length(source_antibiotics) == 2) { + rows <- tryCatch(which(tbl_[, col_mo_property] %like% mo_value + & tbl_[, source_antibiotics[1L]] == source_value[1L] + & tbl_[, source_antibiotics[2L]] == source_value[2L]), + error = function(e) integer(0)) + } else if (length(source_antibiotics) == 3) { + rows <- tryCatch(which(tbl_[, col_mo_property] %like% mo_value + & tbl_[, source_antibiotics[1L]] == source_value[1L] + & tbl_[, source_antibiotics[2L]] == source_value[2L] + & tbl_[, source_antibiotics[3L]] == source_value[3L]), + error = function(e) integer(0)) + } else { + stop("only 3 antibiotics supported for source_antibiotics ", call. = FALSE) + } + } + + cols <- get_antibiotic_columns(target_antibiotics, tbl_) + + # Apply rule on data ------------------------------------------------------ + # this will return the unique number of changes + no_of_changes <- no_of_changes + edit_rsi(to = target_value, + rule = c(rule_text, rule_group_current, rule_current), + rows = rows, + cols = cols) + + # Print number of new changes --------------------------------------------- + if (info == TRUE & rule_next != rule_current) { + # print only on last one of rules in this group + txt_ok(no_of_changes = no_of_changes) + no_of_changes <- 0 + } + } + + # Print overview ---------------------------------------------------------- if (info == TRUE) { if (verbose == TRUE) { wouldve <- "would have " } else { wouldve <- "" } - if (sum(number_added_S, number_added_I, number_added_R, - number_changed_to_S, number_changed_to_I, number_changed_to_R, - na.rm = TRUE) == 0) { - colour <- green # is function - } else { - colour <- blue # is function - } + + verbose_info <- verbose_info %>% + arrange(row, rule_group, rule_name, col) + decimal.mark <- getOption("OutDec") big.mark <- ifelse(decimal.mark != ",", ",", ".") formatnr <- function(x) { - format(x, big.mark = big.mark, decimal.mark = decimal.mark) + trimws(format(x, big.mark = big.mark, decimal.mark = decimal.mark)) } - cat(bold(paste('\n=> EUCAST rules', paste0(wouldve, 'affected'), - number_affected_rows %>% length() %>% formatnr(), - 'out of', nrow(tbl_original) %>% formatnr(), - 'rows\n'))) - total_added <- number_added_S + number_added_I + number_added_R - total_changed <- number_changed_to_S + number_changed_to_I + number_changed_to_R - cat(colour(paste0(" -> ", wouldve, "added ", - bold(formatnr(total_added), "test results"), - if(total_added > 0) - paste0(" (", formatnr(number_added_S), " as S; ", - formatnr(number_added_I), " as I; ", - formatnr(number_added_R), " as R)"), + + cat(paste0("\n", silver(strrep("-", options()$width - 1)), "\n")) + cat(bold(paste('EUCAST rules', paste0(wouldve, 'affected'), + formatnr(n_distinct(verbose_info$row)), + 'out of', formatnr(nrow(tbl_original)), + 'rows, making a total of', formatnr(nrow(verbose_info)), 'edits\n'))) + + # print added values ---- + if (verbose_info %>% filter(is.na(old)) %>% nrow() == 0) { + colour <- cat # is function + } else { + colour <- blue # is function + } + cat(colour(paste0("=> ", wouldve, "added ", + bold(formatnr(verbose_info %>% + filter(is.na(old)) %>% + nrow()), "test results"), "\n"))) - cat(colour(paste0(" -> ", wouldve, "changed ", - bold(formatnr(total_changed), "test results"), - if(total_changed > 0) - paste0(" (", formatnr(number_changed_to_S), " to S; ", - formatnr(number_changed_to_I), " to I; ", - formatnr(number_changed_to_R), " to R)"), + if (verbose_info %>% filter(is.na(old)) %>% nrow() > 0) { + verbose_info %>% + filter(is.na(old)) %>% + # sort it well: S < I < R + mutate(new = as.rsi(new)) %>% + group_by(new) %>% + summarise(n = n()) %>% + mutate(plural = ifelse(n > 1, "s", ""), + txt = paste0(formatnr(n), " test result", plural, " added as ", new)) %>% + pull(txt) %>% + paste(" -", ., collapse = "\n") %>% + cat() + } + + # print changed values ---- + if (verbose_info %>% filter(!is.na(old)) %>% nrow() == 0) { + colour <- cat # is function + } else { + colour <- blue # is function + } + cat(colour(paste0("\n=> ", wouldve, "changed ", + bold(formatnr(verbose_info %>% + filter(!is.na(old)) %>% + nrow()), "test results"), "\n"))) - if (verbose == FALSE) { - cat(paste("Use", bold("verbose = TRUE"), "to get a data.frame with all specified edits.\n")) + if (verbose_info %>% filter(!is.na(old)) %>% nrow() > 0) { + verbose_info %>% + filter(!is.na(old)) %>% + # sort it well: S < I < R + mutate(old = as.rsi(old), + new = as.rsi(new)) %>% + group_by(old, new) %>% + summarise(n = n()) %>% + mutate(plural = ifelse(n > 1, "s", ""), + txt = paste0(formatnr(n), " test result", plural, " changed from ", old, " to ", new)) %>% + pull(txt) %>% + paste(" -", ., collapse = "\n") %>% + cat() + cat("\n") + } + cat(paste0(silver(strrep("-", options()$width - 1)), "\n")) + + if (verbose == FALSE & nrow(verbose_info) > 0) { + cat(paste("\nUse", bold("verbose = TRUE"), "to get a data.frame with all specified edits instead.\n")) } } + # Return data set --------------------------------------------------------- if (verbose == TRUE) { - suppressWarnings( - suppressMessages( - verbose_info$mo_fullname <- mo_fullname(verbose_info$mo) - ) - ) - verbose_info <- verbose_info %>% - filter(!is.na(new) & !identical(old, new)) %>% - arrange(row) - return(verbose_info) + verbose_info + } else { + tbl_original } - - tbl_original } #' @rdname eucast_rules +#' @importFrom dplyr %>% arrange #' @export -EUCAST_rules <- function(...) { - .Deprecated("eucast_rules") - eucast_rules(...) +eucast_rules_file <- function() { + utils::read.delim(file = EUCAST_RULES_FILE_LOCATION, + sep = "\t", + stringsAsFactors = FALSE, + header = TRUE, + strip.white = TRUE, + na = c(NA, "", NULL)) %>% + arrange(reference.rule_group, + reference.rule) } - -#' @rdname eucast_rules -#' @export -interpretive_reading <- function(...) { - .Deprecated("eucast_rules") - eucast_rules(...) -} - diff --git a/R/filter_ab_class.R b/R/filter_ab_class.R index 5d4c71a9..9b7c4631 100644 --- a/R/filter_ab_class.R +++ b/R/filter_ab_class.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Filter isolates on result in antibiotic class diff --git a/R/first_isolate.R b/R/first_isolate.R index deb9da10..7993694a 100755 --- a/R/first_isolate.R +++ b/R/first_isolate.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Determine first (weighted) isolates diff --git a/R/freq.R b/R/freq.R index ac3e1655..a4ef129c 100755 --- a/R/freq.R +++ b/R/freq.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Frequency table diff --git a/R/g.test.R b/R/g.test.R index 3d05d079..10a70572 100755 --- a/R/g.test.R +++ b/R/g.test.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' \emph{G}-test for Count Data diff --git a/R/get_locale.R b/R/get_locale.R index e67f6fd4..fc6584ad 100755 --- a/R/get_locale.R +++ b/R/get_locale.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Get language for AMR diff --git a/R/ggplot_rsi.R b/R/ggplot_rsi.R index 9a2d8730..988c99b2 100755 --- a/R/ggplot_rsi.R +++ b/R/ggplot_rsi.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' AMR plots with \code{ggplot2} diff --git a/R/globals.R b/R/globals.R index 9590ebc4..df54682c 100755 --- a/R/globals.R +++ b/R/globals.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # globalVariables(c(".", @@ -28,6 +28,7 @@ globalVariables(c(".", "authors", "Becker", "certe", + "CNS_CPS", "cnt", "col_id", "count", @@ -46,8 +47,8 @@ globalVariables(c(".", "genus", "gramstain", "index", - "Interpretation", "input", + "Interpretation", "item", "key_ab", "key_ab_lag", @@ -81,6 +82,7 @@ globalVariables(c(".", "Pasted", "patient_id", "phylum", + "plural", "prevalence", "prevalent", "property", @@ -88,6 +90,10 @@ globalVariables(c(".", "R", "real_first_isolate", "ref", + "reference.rule", + "reference.rule_group", + "rule_group", + "rule_name", "S", "se_max", "se_min", @@ -101,6 +107,7 @@ globalVariables(c(".", "transmute", "tsn", "tsn_new", + "txt", "umcg", "value", "Value", diff --git a/R/guess_ab_col.R b/R/guess_ab_col.R index a94a971a..095ad469 100755 --- a/R/guess_ab_col.R +++ b/R/guess_ab_col.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Guess antibiotic column diff --git a/R/join_microorganisms.R b/R/join_microorganisms.R index 15b4cf64..7121f613 100755 --- a/R/join_microorganisms.R +++ b/R/join_microorganisms.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Join a table with \code{microorganisms} diff --git a/R/key_antibiotics.R b/R/key_antibiotics.R index 17310e5f..67527eeb 100755 --- a/R/key_antibiotics.R +++ b/R/key_antibiotics.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Key antibiotics for first \emph{weighted} isolates diff --git a/R/kurtosis.R b/R/kurtosis.R index aa9daf3e..cc715be6 100755 --- a/R/kurtosis.R +++ b/R/kurtosis.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Kurtosis of the sample diff --git a/R/like.R b/R/like.R index f606c986..c46595e9 100755 --- a/R/like.R +++ b/R/like.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Pattern Matching diff --git a/R/mdro.R b/R/mdro.R index 1602db3d..24aac652 100755 --- a/R/mdro.R +++ b/R/mdro.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Determine multidrug-resistant organisms (MDRO) diff --git a/R/mic.R b/R/mic.R index 374fe55b..502eaebf 100755 --- a/R/mic.R +++ b/R/mic.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Class 'mic' diff --git a/R/misc.R b/R/misc.R index 2217b850..43ee9dc9 100755 --- a/R/misc.R +++ b/R/misc.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # # No export, no Rd @@ -76,18 +76,18 @@ check_available_columns <- function(tbl, col.list, info = TRUE) { # are they available as upper case or lower case then? for (i in 1:length(col.list)) { if (is.null(col.list[i]) | isTRUE(is.na(col.list[i]))) { - col.list[i] <- NULL + col.list[i] <- NA } else if (toupper(col.list[i]) %in% colnames(tbl)) { col.list[i] <- toupper(col.list[i]) } else if (tolower(col.list[i]) %in% colnames(tbl)) { col.list[i] <- tolower(col.list[i]) } else if (!col.list[i] %in% colnames(tbl)) { - col.list[i] <- NULL + col.list[i] <- NA } } if (!all(col.list %in% colnames(tbl))) { if (info == TRUE) { - warning('These columns do not exist and will be ignored: ', + warning('Some columns do not exist and will be ignored: ', col.list.bak[!(col.list %in% colnames(tbl))] %>% toString(), '.\nTHIS MAY STRONGLY INFLUENCE THE OUTCOME.', immediate. = TRUE, diff --git a/R/mo.R b/R/mo.R index b30aed52..860a6bec 100755 --- a/R/mo.R +++ b/R/mo.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Transform to microorganism ID @@ -229,7 +229,6 @@ as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, allow_uncertain = TRUE, & isFALSE(Lancefield)) { y <- x - } else if (!any(is.na(mo_hist)) & isFALSE(Becker) & isFALSE(Lancefield)) { diff --git a/R/mo_history.R b/R/mo_history.R index b6a9e0f3..54098efc 100644 --- a/R/mo_history.R +++ b/R/mo_history.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # # print successful as.mo coercions to AMR environment diff --git a/R/mo_property.R b/R/mo_property.R index 1d3faccb..1cf4e6e3 100755 --- a/R/mo_property.R +++ b/R/mo_property.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Property of a microorganism @@ -136,7 +136,7 @@ mo_fullname <- function(x, language = get_locale(), ...) { } #' @rdname mo_property -#' @importFrom dplyr %>% left_join mutate pull +#' @importFrom dplyr %>% mutate pull #' @export mo_shortname <- function(x, language = get_locale(), ...) { dots <- list(...) @@ -247,7 +247,12 @@ mo_phylum <- function(x, language = get_locale(), ...) { #' @rdname mo_property #' @export mo_kingdom <- function(x, language = get_locale(), ...) { - mo_translate(mo_validate(x = x, property = "kingdom", ...), language = language) + kngdm <- mo_validate(x = x, property = "kingdom", ...) + if (language != "en") { + unknowns <- as.mo(x, ...) == "UNKOWN" + kngdm[unknowns] <- mo_translate(kngdm[unknowns], language = language) + } + kngdm } #' @rdname mo_property @@ -260,14 +265,14 @@ mo_type <- function(x, language = get_locale(), ...) { #' @export mo_gramstain <- function(x, language = get_locale(), ...) { x.bak <- x - x.mo <- as.mo(x, ...) - x.phylum <- mo_phylum(x.mo) + x.mo <- as.mo(x, language = "en", ...) + x.phylum <- mo_phylum(x.mo, language = "en") x[x.phylum %in% c("Actinobacteria", "Chloroflexi", "Firmicutes", "Tenericutes")] <- "Gram positive" x[x != "Gram positive"] <- "Gram negative" - x[mo_kingdom(x.mo) != "Bacteria"] <- NA_character_ + x[mo_kingdom(x.mo, language = "en") != "Bacteria"] <- NA_character_ x[x.mo == "B_GRAMP"] <- "Gram positive" x[x.mo == "B_GRAMN"] <- "Gram negative" diff --git a/R/mo_source.R b/R/mo_source.R index cd1f2365..28659607 100644 --- a/R/mo_source.R +++ b/R/mo_source.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Use predefined reference data set diff --git a/R/p.symbol.R b/R/p.symbol.R index b5d67367..ffd4c8a2 100755 --- a/R/p.symbol.R +++ b/R/p.symbol.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Symbol of a p value diff --git a/R/portion.R b/R/portion.R index 278c9723..31a73caf 100755 --- a/R/portion.R +++ b/R/portion.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Calculate resistance of isolates @@ -100,14 +100,14 @@ #' #' # Calculate co-resistance between amoxicillin/clav acid and gentamicin, #' # so we can see that combination therapy does a lot more than mono therapy: -#' septic_patients %>% portion_S(amcl) # S = 67.1% -#' septic_patients %>% count_all(amcl) # n = 1576 +#' septic_patients %>% portion_S(amcl) # S = 71.4% +#' septic_patients %>% count_all(amcl) # n = 1879 #' #' septic_patients %>% portion_S(gent) # S = 74.0% #' septic_patients %>% count_all(gent) # n = 1855 #' -#' septic_patients %>% portion_S(amcl, gent) # S = 92.0% -#' septic_patients %>% count_all(amcl, gent) # n = 1517 +#' septic_patients %>% portion_S(amcl, gent) # S = 92.3% +#' septic_patients %>% count_all(amcl, gent) # n = 1798 #' #' #' septic_patients %>% diff --git a/R/read.4d.R b/R/read.4d.R index d6f7bb4e..693a32d6 100755 --- a/R/read.4d.R +++ b/R/read.4d.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Read data from 4D database diff --git a/R/resistance_predict.R b/R/resistance_predict.R index 55e60d92..12249939 100755 --- a/R/resistance_predict.R +++ b/R/resistance_predict.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Predict antimicrobial resistance diff --git a/R/rsi.R b/R/rsi.R index cdbdf93b..a7cde301 100755 --- a/R/rsi.R +++ b/R/rsi.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Class 'rsi' @@ -114,7 +114,12 @@ mic_like <- function(x) { gsub("[^0-9.,]+", "", .) %>% unique() mic_valid <- suppressWarnings(as.mic(mic)) - sum(!is.na(mic_valid)) / length(mic) + result <- sum(!is.na(mic_valid)) / length(mic) + if (is.na(result)) { + 0 + } else { + result + } } #' @rdname as.rsi diff --git a/R/rsi_calc.R b/R/rsi_calc.R index ca5a8843..a579a1ad 100755 --- a/R/rsi_calc.R +++ b/R/rsi_calc.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' @importFrom dplyr %>% pull all_vars any_vars filter_all funs mutate_all diff --git a/R/skewness.R b/R/skewness.R index 2cf6c5a4..b3cad0a0 100755 --- a/R/skewness.R +++ b/R/skewness.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' Skewness of the sample diff --git a/R/whocc.R b/R/whocc.R index 846e7990..61ac3808 100755 --- a/R/whocc.R +++ b/R/whocc.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' WHOCC: WHO Collaborating Centre for Drug Statistics Methodology diff --git a/R/zzz.R b/R/zzz.R index 6d4a87df..24f915a2 100755 --- a/R/zzz.R +++ b/R/zzz.R @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # #' @importFrom data.table as.data.table setkey @@ -44,6 +44,15 @@ assign(x = "mo_codes_v0.5.0", value = make_trans_tbl(), envir = asNamespace("AMR")) + + assign(x = "mo_history", + value = data.frame(x = character(0), + mo = character(0), + uncertainty_level = integer(0), + package_v = character(0), + stringsAsFactors = FALSE), + envir = asNamespace("AMR")) + } #' @importFrom dplyr mutate case_when diff --git a/_pkgdown.yml b/_pkgdown.yml index 5052090d..e2b69889 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # url: 'https://msberends.gitlab.io/AMR' diff --git a/appveyor.yml b/appveyor.yml index a241a40d..f82022c8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ # This R package was created for academic research and was publicly # # released in the hope that it will be useful, but it comes WITHOUT # # ANY WARRANTY OR LIABILITY. # -# Visit our website for more info: https://msberends.gitab.io/AMR. # +# Visit our website for more info: https://msberends.gitlab.io/AMR. # # ==================================================================== # # Download script file from GitHub diff --git a/data/WHONET.rda b/data/WHONET.rda index 9a079c86..144c0cb2 100644 Binary files a/data/WHONET.rda and b/data/WHONET.rda differ diff --git a/data/microorganisms.old.rda b/data/microorganisms.old.rda index a6082ecb..bfa33f47 100644 Binary files a/data/microorganisms.old.rda and b/data/microorganisms.old.rda differ diff --git a/data/microorganisms.rda b/data/microorganisms.rda index d2e4c1d1..1269a0b3 100755 Binary files a/data/microorganisms.rda and b/data/microorganisms.rda differ diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index 3cf55fe5..ae2c6d42 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -78,7 +78,7 @@
diff --git a/docs/articles/AMR.html b/docs/articles/AMR.html index d2cef62d..0f2d78dd 100644 --- a/docs/articles/AMR.html +++ b/docs/articles/AMR.html @@ -40,7 +40,7 @@ @@ -192,7 +192,7 @@AMR.Rmd
Note: values on this page will change with every website update since they are based on randomly created values and the page was written in R Markdown. However, the methodology remains unchanged. This page was generated on 27 March 2019.
+Note: values on this page will change with every website update since they are based on randomly created values and the page was written in R Markdown. However, the methodology remains unchanged. This page was generated on 05 April 2019.
So, we can draw at least two conclusions immediately. From a data scientist perspective, the data looks clean: only values M
and F
. From a researcher perspective: there are slightly more men. Nothing we didn’t already know.
The data is already quite clean, but we still need to transform some variables. The bacteria
column now consists of text, and we want to add more variables based on microbial IDs later on. So, we will transform this column to valid IDs. The mutate()
function of the dplyr
package makes this really easy:
data <- data %>%
@@ -425,46 +425,59 @@
data <- eucast_rules(data, col_mo = "bacteria")
#>
#> Rules by the European Committee on Antimicrobial Susceptibility Testing (EUCAST)
-#>
-#> EUCAST Clinical Breakpoints (v9.0, 2019)
-#> Enterobacteriales (Order) (no changes)
-#> Staphylococcus (no changes)
-#> Enterococcus (no changes)
-#> Streptococcus groups A, B, C, G (no changes)
-#> Streptococcus pneumoniae (no changes)
-#> Viridans group streptococci (no changes)
-#> Haemophilus influenzae (no changes)
-#> Moraxella catarrhalis (no changes)
-#> Anaerobic Gram positives (no changes)
-#> Anaerobic Gram negatives (no changes)
-#> Pasteurella multocida (no changes)
-#> Campylobacter jejuni and C. coli (no changes)
-#> Aerococcus sanguinicola and A. urinae (no changes)
-#> Kingella kingae (no changes)
-#>
-#> EUCAST Expert Rules, Intrinsic Resistance and Exceptional Phenotypes (v3.1, 2016)
-#> Table 1: Intrinsic resistance in Enterobacteriaceae (1342 changes)
-#> Table 2: Intrinsic resistance in non-fermentative Gram-negative bacteria (no changes)
-#> Table 3: Intrinsic resistance in other Gram-negative bacteria (no changes)
-#> Table 4: Intrinsic resistance in Gram-positive bacteria (2726 changes)
-#> Table 8: Interpretive rules for B-lactam agents and Gram-positive cocci (no changes)
-#> Table 9: Interpretive rules for B-lactam agents and Gram-negative rods (no changes)
-#> Table 10: Interpretive rules for B-lactam agents and other Gram-negative bacteria (no changes)
-#> Table 11: Interpretive rules for macrolides, lincosamides, and streptogramins (no changes)
-#> Table 12: Interpretive rules for aminoglycosides (no changes)
-#> Table 13: Interpretive rules for quinolones (no changes)
-#>
-#> Other rules
-#> Non-EUCAST: ampicillin = R where amoxicillin/clav acid = R (no changes)
-#> Non-EUCAST: piperacillin = R where piperacillin/tazobactam = R (no changes)
-#> Non-EUCAST: trimethoprim = R where trimethoprim/sulfa = R (no changes)
-#> Non-EUCAST: amoxicillin/clav acid = S where ampicillin = S (no changes)
-#> Non-EUCAST: piperacillin/tazobactam = S where piperacillin = S (no changes)
-#> Non-EUCAST: trimethoprim/sulfa = S where trimethoprim = S (no changes)
-#>
-#> => EUCAST rules affected 7,400 out of 20,000 rows
-#> -> added 0 test results
-#> -> changed 4,068 test results (0 to S; 0 to I; 4,068 to R)
+#> http://eucast.org/
+#>
+#> EUCAST Clinical Breakpoints (v9.0, 2019)
+#> Aerococcus sanguinicola (no new changes)
+#> Aerococcus urinae (no new changes)
+#> Anaerobic Gram negatives (no new changes)
+#> Anaerobic Gram positives (no new changes)
+#> Campylobacter coli (no new changes)
+#> Campylobacter jejuni (no new changes)
+#> Enterobacteriales (Order) (no new changes)
+#> Enterococcus (no new changes)
+#> Haemophilus influenzae (no new changes)
+#> Kingella kingae (no new changes)
+#> Moraxella catarrhalis (no new changes)
+#> Pasteurella multocida (no new changes)
+#> Staphylococcus (no new changes)
+#> Streptococcus groups A, B, C, G (no new changes)
+#> Streptococcus pneumoniae (1476 new changes)
+#> Viridans group streptococci (no new changes)
+#>
+#> EUCAST Expert Rules, Intrinsic Resistance and Exceptional Phenotypes (v3.1, 2016)
+#> Table 01: Intrinsic resistance in Enterobacteriaceae (1290 new changes)
+#> Table 02: Intrinsic resistance in non-fermentative Gram-negative bacteria (no new changes)
+#> Table 03: Intrinsic resistance in other Gram-negative bacteria (no new changes)
+#> Table 04: Intrinsic resistance in Gram-positive bacteria (2758 new changes)
+#> Table 08: Interpretive rules for B-lactam agents and Gram-positive cocci (no new changes)
+#> Table 09: Interpretive rules for B-lactam agents and Gram-negative rods (no new changes)
+#> Table 11: Interpretive rules for macrolides, lincosamides, and streptogramins (no new changes)
+#> Table 12: Interpretive rules for aminoglycosides (no new changes)
+#> Table 13: Interpretive rules for quinolones (no new changes)
+#>
+#> Other rules
+#> Non-EUCAST: amoxicillin/clav acid = S where ampicillin = S (2311 new changes)
+#> Non-EUCAST: ampicillin = R where amoxicillin/clav acid = R (107 new changes)
+#> Non-EUCAST: piperacillin = R where piperacillin/tazobactam = R (no new changes)
+#> Non-EUCAST: piperacillin/tazobactam = S where piperacillin = S (no new changes)
+#> Non-EUCAST: trimethoprim = R where trimethoprim/sulfa = R (no new changes)
+#> Non-EUCAST: trimethoprim/sulfa = S where trimethoprim = S (no new changes)
+#>
+#> --------------------------------------------------------------------------
+#> EUCAST rules affected 6,584 out of 20,000 rows, making a total of 7,942 edits
+#> => added 0 test results
+#>
+#> => changed 7,942 test results
+#> - 125 test results changed from S to I
+#> - 4,719 test results changed from S to R
+#> - 1,093 test results changed from I to S
+#> - 299 test results changed from I to R
+#> - 1,682 test results changed from R to S
+#> - 24 test results changed from R to I
+#> --------------------------------------------------------------------------
+#>
+#> Use verbose = TRUE to get a data.frame with all specified edits instead.
So only 28.3% is suitable for resistance analysis! We can now filter on it with the filter()
function, also from the dplyr
package:
So only 28.4% is suitable for resistance analysis! We can now filter on it with the filter()
function, also from the dplyr
package:
For future use, the above two syntaxes can be shortened with the filter_first_isolate()
function:
isolate | @@ -654,11 +667,11 @@|||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | -2010-09-11 | -L7 | +2010-01-24 | +N5 | B_ESCHR_COL | -R | -I | +S | +S | S | S | TRUE | @@ -666,119 +679,119 @@|
2 | -2010-11-07 | -L7 | +2010-07-22 | +N5 | B_ESCHR_COL | S | S | S | -R | +S | +FALSE | FALSE | -TRUE |
3 | -2011-01-16 | -L7 | +2010-07-29 | +N5 | B_ESCHR_COL | -S | R | S | S | +S | FALSE | TRUE | |
4 | -2011-02-25 | -L7 | +2010-09-17 | +N5 | B_ESCHR_COL | R | -S | +I | S | S | FALSE | -TRUE | +FALSE |
5 | -2011-08-07 | -L7 | +2011-02-27 | +N5 | B_ESCHR_COL | S | S | S | S | -FALSE | +TRUE | TRUE | |
6 | -2011-08-16 | -L7 | +2011-04-25 | +N5 | B_ESCHR_COL | S | S | -R | +S | S | FALSE | -TRUE | +FALSE |
7 | -2011-10-08 | -L7 | +2011-04-30 | +N5 | B_ESCHR_COL | S | -R | -S | -S | -TRUE | -TRUE | -||
8 | -2011-10-26 | -L7 | -B_ESCHR_COL | -R | S | S | S | FALSE | -TRUE | +FALSE | +|||
8 | +2011-05-27 | +N5 | +B_ESCHR_COL | +S | +S | +S | +S | +FALSE | +FALSE | ||||
9 | -2012-01-15 | -L7 | +2011-06-24 | +N5 | B_ESCHR_COL | -S | -I | R | S | +S | +S | FALSE | TRUE |
10 | -2012-02-08 | -L7 | +2011-10-29 | +N5 | B_ESCHR_COL | +R | S | -S | -S | +R | S | FALSE | TRUE |
Instead of 2, now 10 isolates are flagged. In total, 78.6% of all isolates are marked ‘first weighted’ - 50.3% more than when using the CLSI guideline. In real life, this novel algorithm will yield 5-10% more isolates than the classic CLSI guideline.
+Instead of 2, now 5 isolates are flagged. In total, 75.3% of all isolates are marked ‘first weighted’ - 46.9% more than when using the CLSI guideline. In real life, this novel algorithm will yield 5-10% more isolates than the classic CLSI guideline.
As with filter_first_isolate()
, there’s a shortcut for this new algorithm too:
So we end up with 15,729 isolates for analysis.
+So we end up with 15,059 isolates for analysis.
We can remove unneeded columns:
@@ -802,13 +815,58 @@Or can be used like the dplyr
way, which is easier readable:
Frequency table of genus
and species
from a data.frame
(15,729 x 13)
Frequency table of genus
and species
from a data.frame
(15,059 x 13)
Columns: 2
-Length: 15,729 (of which NA: 0 = 0.00%)
+Length: 15,059 (of which NA: 0 = 0.00%)
Unique: 4
Shortest: 16
Longest: 24
The functions portion_S()
, portion_SI()
, portion_I()
, portion_IR()
and portion_R()
can be used to determine the portion of a specific antimicrobial outcome. They can be used on their own:
Or can be used in conjuction with group_by()
and summarise()
, both from the dplyr
package:
data_1st %>%
group_by(hospital) %>%
@@ -977,19 +990,19 @@ Longest: 24
Hospital A
-0.4841779
+0.5037963
Hospital B
-0.4800215
+0.5007457
Hospital C
-0.4663419
+0.5111524
Hospital D
-0.4815057
+0.4851550
@@ -1007,23 +1020,23 @@ Longest: 24
Hospital A
-0.4841779
-4835
+0.5037963
+4478
Hospital B
-0.4800215
-5581
+0.5007457
+5364
Hospital C
-0.4663419
-2258
+0.5111524
+2152
Hospital D
-0.4815057
-3055
+0.4851550
+3065
@@ -1043,27 +1056,27 @@ Longest: 24
Escherichia
-0.7376713
-0.8986807
-0.9754067
+0.8796370
+0.8973846
+0.9902589
Klebsiella
-0.7305010
-0.8953710
-0.9727330
+0.7172942
+0.9081047
+0.9821315
Staphylococcus
-0.7305435
-0.9275325
-0.9793315
+0.8829295
+0.9221345
+0.9918323
Streptococcus
-0.7320692
+0.5767742
0.0000000
-0.7320692
+0.5767742
diff --git a/docs/articles/AMR_files/figure-html/plot 1-1.png b/docs/articles/AMR_files/figure-html/plot 1-1.png
index b76ef17b..e19ff0cd 100644
Binary files a/docs/articles/AMR_files/figure-html/plot 1-1.png and b/docs/articles/AMR_files/figure-html/plot 1-1.png differ
diff --git a/docs/articles/AMR_files/figure-html/plot 3-1.png b/docs/articles/AMR_files/figure-html/plot 3-1.png
index a6b86eeb..ddcb0034 100644
Binary files a/docs/articles/AMR_files/figure-html/plot 3-1.png and b/docs/articles/AMR_files/figure-html/plot 3-1.png differ
diff --git a/docs/articles/AMR_files/figure-html/plot 4-1.png b/docs/articles/AMR_files/figure-html/plot 4-1.png
index 9bc0d924..0f6db905 100644
Binary files a/docs/articles/AMR_files/figure-html/plot 4-1.png and b/docs/articles/AMR_files/figure-html/plot 4-1.png differ
diff --git a/docs/articles/AMR_files/figure-html/plot 5-1.png b/docs/articles/AMR_files/figure-html/plot 5-1.png
index 95f86455..9ca46f79 100644
Binary files a/docs/articles/AMR_files/figure-html/plot 5-1.png and b/docs/articles/AMR_files/figure-html/plot 5-1.png differ
diff --git a/docs/articles/SPSS.html b/docs/articles/SPSS.html
index 30afa341..4ff4c81f 100644
--- a/docs/articles/SPSS.html
+++ b/docs/articles/SPSS.html
@@ -40,7 +40,7 @@
SPSS.Rmd
benchmarks.Rmd
In the table above, all measurements are shown in milliseconds (thousands of seconds). A value of 5 milliseconds means it can determine 200 input values per second. It case of 100 milliseconds, this is only 10 input values per second. The second input is the only one that has to be looked up thoroughly. All the others are known codes (the first one is a WHONET code) or common laboratory codes, or common full organism names like the last one. Full organism names are always preferred.
To achieve this speed, the as.mo
function also takes into account the prevalence of human pathogenic microorganisms. The downside is of course that less prevalent microorganisms will be determined less fast. See this example for the ID of Thermus islandicus (B_THERMS_ISL
), a bug probably never found before in humans:
T.islandicus <- microbenchmark(as.mo("theisl"),
@@ -236,12 +236,12 @@
print(T.islandicus, unit = "ms", signif = 2)
#> Unit: milliseconds
#> expr min lq mean median uq max neval
-#> as.mo("theisl") 460 460 500 510 510 560 10
-#> as.mo("THEISL") 460 470 490 490 510 530 10
-#> as.mo("T. islandicus") 74 74 84 75 78 120 10
-#> as.mo("T. islandicus") 74 75 88 75 120 120 10
-#> as.mo("Thermus islandicus") 73 73 84 74 75 130 10
That takes 7.6 times as much time on average. A value of 100 milliseconds means it can only determine ~10 different input values per second. We can conclude that looking up arbitrary codes of less prevalent microorganisms is the worst way to go, in terms of calculation performance. Full names (like Thermus islandicus) are almost fast - these are the most probable input from most data sets.
+#> as.mo("theisl") 460 460 480 470 510 510 10 +#> as.mo("THEISL") 460 470 490 490 510 540 10 +#> as.mo("T. islandicus") 73 73 84 73 77 130 10 +#> as.mo("T. islandicus") 73 73 88 75 120 120 10 +#> as.mo("Thermus islandicus") 73 73 80 73 74 130 10 +That takes 8 times as much time on average. A value of 100 milliseconds means it can only determine ~10 different input values per second. We can conclude that looking up arbitrary codes of less prevalent microorganisms is the worst way to go, in terms of calculation performance. Full names (like Thermus islandicus) are almost fast - these are the most probable input from most data sets.
In the figure below, we compare Escherichia coli (which is very common) with Prevotella brevis (which is moderately common) and with Thermus islandicus (which is very uncommon):
par(mar = c(5, 16, 4, 2)) # set more space for left margin text (16)
@@ -257,111 +257,110 @@
main = "Benchmarks per prevalence")
In reality, the as.mo()
functions learns from its own output to speed up determinations for next times. In above figure, this effect was disabled to show the difference with the boxplot below - when you would use as.mo()
yourself:
#> File /home/uscloud/.Rhistory_mo removed.
-The highest outliers are the first times. All next determinations were done in only thousands of seconds.
+The highest outliers are the first times. All next determinations were done in only thousands of seconds. For now, learning only works per session. If R is closed or terminated, the algorithms reset. This will probably be resolved in a next version.
Still, uncommon microorganisms take a lot more time than common microorganisms, especially the first time. To relieve this pitfall and further improve performance, two important calculations take almost no time at all: repetitive results and already precalculated results.
Repetitive results are unique values that are present more than once. Unique values will only be calculated once by as.mo()
. We will use mo_fullname()
for this test - a helper function that returns the full microbial name (genus, species and possibly subspecies) which uses as.mo()
internally.
library(dplyr)
-# take all MO codes from the septic_patients data set
-x <- septic_patients$mo %>%
- # keep only the unique ones
- unique() %>%
- # pick 50 of them at random
- sample(50) %>%
- # paste that 10,000 times
- rep(10000) %>%
- # scramble it
- sample()
-
-# got indeed 50 times 10,000 = half a million?
-length(x)
-#> [1] 500000
-
-# and how many unique values do we have?
-n_distinct(x)
-#> [1] 50
-
-# now let's see:
-run_it <- microbenchmark(mo_fullname(x),
- times = 10)
-print(run_it, unit = "ms", signif = 3)
-#> Unit: milliseconds
-#> expr min lq mean median uq max neval
-#> mo_fullname(x) 825 845 887 867 903 1080 10
So transforming 500,000 values (!!) of 50 unique values only takes 0.87 seconds (867 ms). You only lose time on your unique input values.
+library(dplyr)
+# take all MO codes from the septic_patients data set
+x <- septic_patients$mo %>%
+ # keep only the unique ones
+ unique() %>%
+ # pick 50 of them at random
+ sample(50) %>%
+ # paste that 10,000 times
+ rep(10000) %>%
+ # scramble it
+ sample()
+
+# got indeed 50 times 10,000 = half a million?
+length(x)
+#> [1] 500000
+
+# and how many unique values do we have?
+n_distinct(x)
+#> [1] 50
+
+# now let's see:
+run_it <- microbenchmark(mo_fullname(x),
+ times = 10)
+print(run_it, unit = "ms", signif = 3)
+#> Unit: milliseconds
+#> expr min lq mean median uq max neval
+#> mo_fullname(x) 689 730 762 752 778 938 10
So transforming 500,000 values (!!) of 50 unique values only takes 0.75 seconds (751 ms). You only lose time on your unique input values.
What about precalculated results? If the input is an already precalculated result of a helper function like mo_fullname()
, it almost doesn’t take any time at all (see ‘C’ below):
run_it <- microbenchmark(A = mo_fullname("B_STPHY_AUR"),
- B = mo_fullname("S. aureus"),
- C = mo_fullname("Staphylococcus aureus"),
- times = 10)
-print(run_it, unit = "ms", signif = 3)
-#> Unit: milliseconds
-#> expr min lq mean median uq max neval
-#> A 12.400 12.700 13.100 13.000 13.400 13.700 10
-#> B 26.300 26.600 27.900 28.400 28.700 29.000 10
-#> C 0.486 0.502 0.727 0.821 0.849 0.982 10
run_it <- microbenchmark(A = mo_fullname("B_STPHY_AUR"),
+ B = mo_fullname("S. aureus"),
+ C = mo_fullname("Staphylococcus aureus"),
+ times = 10)
+print(run_it, unit = "ms", signif = 3)
+#> Unit: milliseconds
+#> expr min lq mean median uq max neval
+#> A 12.200 12.300 12.500 12.400 12.600 13.40 10
+#> B 25.800 26.300 26.800 26.600 26.900 28.50 10
+#> C 0.477 0.724 0.779 0.825 0.848 1.07 10
So going from mo_fullname("Staphylococcus aureus")
to "Staphylococcus aureus"
takes 0.0008 seconds - it doesn’t even start calculating if the result would be the same as the expected resulting value. That goes for all helper functions:
run_it <- microbenchmark(A = mo_species("aureus"),
- B = mo_genus("Staphylococcus"),
- C = mo_fullname("Staphylococcus aureus"),
- D = mo_family("Staphylococcaceae"),
- E = mo_order("Bacillales"),
- F = mo_class("Bacilli"),
- G = mo_phylum("Firmicutes"),
- H = mo_kingdom("Bacteria"),
- times = 10)
-print(run_it, unit = "ms", signif = 3)
-#> Unit: milliseconds
-#> expr min lq mean median uq max neval
-#> A 0.371 0.432 0.463 0.471 0.500 0.525 10
-#> B 0.479 0.531 0.557 0.553 0.566 0.631 10
-#> C 0.511 0.676 0.834 0.904 0.959 1.090 10
-#> D 0.422 0.444 0.483 0.494 0.501 0.559 10
-#> E 0.383 0.458 0.502 0.477 0.507 0.778 10
-#> F 0.362 0.376 0.476 0.426 0.473 0.947 10
-#> G 0.361 0.368 0.451 0.452 0.500 0.610 10
-#> H 0.359 0.383 0.431 0.437 0.458 0.505 10
run_it <- microbenchmark(A = mo_species("aureus"),
+ B = mo_genus("Staphylococcus"),
+ C = mo_fullname("Staphylococcus aureus"),
+ D = mo_family("Staphylococcaceae"),
+ E = mo_order("Bacillales"),
+ F = mo_class("Bacilli"),
+ G = mo_phylum("Firmicutes"),
+ H = mo_kingdom("Bacteria"),
+ times = 10)
+print(run_it, unit = "ms", signif = 3)
+#> Unit: milliseconds
+#> expr min lq mean median uq max neval
+#> A 0.376 0.386 0.436 0.436 0.479 0.516 10
+#> B 0.467 0.501 0.561 0.567 0.599 0.700 10
+#> C 0.503 0.782 0.850 0.918 0.971 1.040 10
+#> D 0.403 0.471 0.488 0.491 0.525 0.588 10
+#> E 0.343 0.429 0.456 0.445 0.485 0.638 10
+#> F 0.380 0.403 0.447 0.453 0.491 0.520 10
+#> G 0.385 0.421 0.458 0.447 0.487 0.575 10
+#> H 0.396 0.455 0.484 0.491 0.515 0.549 10
Of course, when running mo_phylum("Firmicutes")
the function has zero knowledge about the actual microorganism, namely S. aureus. But since the result would be "Firmicutes"
too, there is no point in calculating the result. And because this package ‘knows’ all phyla of all known bacteria (according to the Catalogue of Life), it can just return the initial value immediately.
When the system language is non-English and supported by this AMR
package, some functions will have a translated result. This almost does’t take extra time:
mo_fullname("CoNS", language = "en") # or just mo_fullname("CoNS") on an English system
-#> [1] "Coagulase-negative Staphylococcus (CoNS)"
-
-mo_fullname("CoNS", language = "es") # or just mo_fullname("CoNS") on a Spanish system
-#> [1] "Staphylococcus coagulasa negativo (SCN)"
-
-mo_fullname("CoNS", language = "nl") # or just mo_fullname("CoNS") on a Dutch system
-#> [1] "Coagulase-negatieve Staphylococcus (CNS)"
-
-run_it <- microbenchmark(en = mo_fullname("CoNS", language = "en"),
- de = mo_fullname("CoNS", language = "de"),
- nl = mo_fullname("CoNS", language = "nl"),
- es = mo_fullname("CoNS", language = "es"),
- it = mo_fullname("CoNS", language = "it"),
- fr = mo_fullname("CoNS", language = "fr"),
- pt = mo_fullname("CoNS", language = "pt"),
- times = 10)
-print(run_it, unit = "ms", signif = 4)
-#> Unit: milliseconds
-#> expr min lq mean median uq max neval
-#> en 18.83 19.19 24.20 19.53 20.67 63.66 10
-#> de 31.53 32.10 36.79 32.22 33.81 75.80 10
-#> nl 31.24 31.78 32.22 32.10 32.24 33.43 10
-#> es 31.40 32.07 45.82 33.08 75.31 76.95 10
-#> it 31.17 31.95 36.82 32.09 32.19 79.48 10
-#> fr 31.48 31.64 31.89 31.96 32.07 32.33 10
-#> pt 31.27 31.66 36.80 32.06 32.34 80.53 10
mo_fullname("CoNS", language = "en") # or just mo_fullname("CoNS") on an English system
+#> [1] "Coagulase-negative Staphylococcus (CoNS)"
+
+mo_fullname("CoNS", language = "es") # or just mo_fullname("CoNS") on a Spanish system
+#> [1] "Staphylococcus coagulasa negativo (SCN)"
+
+mo_fullname("CoNS", language = "nl") # or just mo_fullname("CoNS") on a Dutch system
+#> [1] "Coagulase-negatieve Staphylococcus (CNS)"
+
+run_it <- microbenchmark(en = mo_fullname("CoNS", language = "en"),
+ de = mo_fullname("CoNS", language = "de"),
+ nl = mo_fullname("CoNS", language = "nl"),
+ es = mo_fullname("CoNS", language = "es"),
+ it = mo_fullname("CoNS", language = "it"),
+ fr = mo_fullname("CoNS", language = "fr"),
+ pt = mo_fullname("CoNS", language = "pt"),
+ times = 10)
+print(run_it, unit = "ms", signif = 4)
+#> Unit: milliseconds
+#> expr min lq mean median uq max neval
+#> en 18.96 19.05 19.17 19.10 19.28 19.50 10
+#> de 31.11 31.58 40.75 32.11 33.36 75.57 10
+#> nl 31.18 31.55 39.10 31.77 32.52 75.92 10
+#> es 30.76 31.46 40.46 31.62 33.07 75.85 10
+#> it 31.02 31.41 36.06 31.67 31.95 76.19 10
+#> fr 31.02 31.66 36.36 31.84 32.46 76.22 10
+#> pt 31.13 31.58 31.78 31.65 31.74 33.00 10
Currently supported are German, Dutch, Spanish, Italian, French and Portuguese.
The kingdom of Fungi is a very large taxon with almost 300,000 different (sub)species, of which most are not microbial (but rather macroscopic, like mushrooms). Because of this, not all fungi fit the scope of this package and including everything would tremendously slow down our algorithms too. By only including the aforementioned taxonomic orders, the most relevant fungi are covered (like all species of Aspergillus, Candida, Cryptococcus, Histoplasma, Pneumocystis, Saccharomyces and Trichophyton).
All ~2,000 (sub)species from ~100 other relevant genera, from the kingdoms of Animalia and Plantae (like Strongyloides and Taenia)
All ~15,000 previously accepted names of included (sub)species that have been taxonomically renamed
All ~21,000 previously accepted names of included (sub)species that have been taxonomically renamed
The responsible author(s) and year of scientific publication
This data is updated annually - check the included version with catalogue_of_life_version()
.
Note: latest development version
+guess_mo()
, guess_atc()
, EUCAST_rules()
, interpretive_reading()
+microorganisms.old
data set, which leads to better results finding when using the as.mo()
function./inst/eucast/eucast.tsv
.eucast_rules()
with verbose = TRUE
+New website!
We’ve got a new website: https://msberends.gitlab.io/AMR (built with the great pkgdown
)
as.atc()
New vignettes about how to conduct AMR analysis, predict antimicrobial resistance, use the G-test and more. These are also available (and even easier readable) on our website: https://msberends.gitlab.io/AMR.
eucast_rules()
:
as.atc()
antibiotics
data set, from the Pharmaceuticals Community Register of the European Commissionatc_group1_nl
and atc_group2_nl
from the antibiotics
data setatc_ddd()
and atc_groups()
have been renamed atc_online_ddd()
and atc_online_groups()
. The old functions are deprecated and will be removed in a future version.guess_mo()
is now deprecated in favour of as.mo()
and will be removed in future versionsguess_atc()
is now deprecated in favour of as.atc()
and will be removed in future versionsguess_mo()
is now deprecated in favour of as.mo()
and will be removed in future versionsguess_atc()
is now deprecated in favour of as.atc()
and will be removed in future versionsas.mo()
:
as.mo(..., allow_uncertain = 3)Functions mo_authors
and mo_year
to get specific values about the scientific reference of a taxonomic entry
MDRO
, BRMO
, MRGN
and EUCAST_exceptional_phenotypes
were renamed to mdro
, brmo
, mrgn
and eucast_exceptional_phenotypes
as.mo(..., allow_uncertain = 3)Renamed septic_patients$sex
to septic_patients$gender
antibiotics
data set: Terbinafine (D01BA02), Rifaximin (A07AA11) and Isoconazole (D01AC05)as.mo(..., allow_uncertain = 3)
resistance_predict
and added more examplesas.mo(..., allow_uncertain = 3)New print format for tibble
s and data.table
s
rsi
class for vectors that contain only invalid antimicrobial interpretationsablist
to antibiotics
@@ -949,6 +980,8 @@ Using as.mo(..., allow_uncertain = 3)
Contents
ratio(x, ratio) -guess_mo(...) - -guess_atc(...) - ab_property(...) ab_atc(...) diff --git a/docs/reference/as.mo.html b/docs/reference/as.mo.html index 59321a8d..32ca1fcb 100644 --- a/docs/reference/as.mo.html +++ b/docs/reference/as.mo.html @@ -80,7 +80,7 @@
mo
) typically looks like t
Use the mo_property_*
functions to get properties based on the returned code, see Examples.
The algorithm uses data from the Catalogue of Life (see below) and from one other source (see ?microorganisms
).
Self-learning algoritm
-The as.mo()
function gains experience from previously determined microbial IDs and learns from it. This drastically improves both speed and reliability. Use clean_mo_history()
to reset the algorithms. Only experience from your current AMR
package version is used. This is done because in the future the taxonomic tree (which is included in this package) may change for any organism and it consequently has to rebuild its knowledge. Usually, any guess after the first try runs 80-95% faster than the first try. The algorithm saves its previous findings to ~/.Rhistory_mo
.
as.mo()
function gains experience from previously determined microbial IDs and learns from it. This drastically improves both speed and reliability. Use clean_mo_history()
to reset the algorithms. Only experience from your current AMR
package version is used. This is done because in the future the taxonomic tree (which is included in this package) may change for any organism and it consequently has to rebuild its knowledge.
+Usually, any guess after the first try runs 80-95% faster than the first try.
+For now, learning only works per session. If R is closed or terminated, the algorithms reset. This will probably be resolved in a next version.
Intelligent rules
This function uses intelligent rules to help getting fast and logical results. It tries to find matches in this order:
Valid MO codes and full names: it first searches in already valid MO code and known genus/species combinations
All ~55,000 (sub)species from the kingdoms of Archaea, Bacteria and Protozoa
All ~3,500 (sub)species from these orders of the kingdom of Fungi: Eurotiales, Onygenales, Pneumocystales, Saccharomycetales, Schizosaccharomycetales and Tremellales. The kingdom of Fungi is a very large taxon with almost 300,000 different (sub)species, of which most are not microbial (but rather macroscopic, like mushrooms). Because of this, not all fungi fit the scope of this package and including everything would tremendously slow down our algorithms too. By only including the aforementioned taxonomic orders, the most relevant fungi are covered (like all species of Aspergillus, Candida, Cryptococcus, Histplasma, Pneumocystis, Saccharomyces and Trichophyton).
All ~2,000 (sub)species from ~100 other relevant genera, from the kingdoms of Animalia and Plantae (like Strongyloides and Taenia)
All ~15,000 previously accepted names of included (sub)species that have been taxonomically renamed
All ~21,000 previously accepted names of included (sub)species that have been taxonomically renamed
The complete taxonomic tree of all included (sub)species: from kingdom to subspecies
The responsible author(s) and year of scientific publication
eucast_rules(tbl, col_mo = NULL, info = TRUE, - rules = c("breakpoints", "expert", "other", "all"), verbose = FALSE, - amcl = guess_ab_col(), amik = guess_ab_col(), - amox = guess_ab_col(), ampi = guess_ab_col(), - azit = guess_ab_col(), azlo = guess_ab_col(), - aztr = guess_ab_col(), cefa = guess_ab_col(), - cfep = guess_ab_col(), cfot = guess_ab_col(), - cfox = guess_ab_col(), cfra = guess_ab_col(), - cfta = guess_ab_col(), cftr = guess_ab_col(), - cfur = guess_ab_col(), chlo = guess_ab_col(), - cipr = guess_ab_col(), clar = guess_ab_col(), - clin = guess_ab_col(), clox = guess_ab_col(), - coli = guess_ab_col(), czol = guess_ab_col(), - dapt = guess_ab_col(), doxy = guess_ab_col(), - erta = guess_ab_col(), eryt = guess_ab_col(), - fosf = guess_ab_col(), fusi = guess_ab_col(), - gent = guess_ab_col(), imip = guess_ab_col(), - kana = guess_ab_col(), levo = guess_ab_col(), - linc = guess_ab_col(), line = guess_ab_col(), - mero = guess_ab_col(), mezl = guess_ab_col(), - mino = guess_ab_col(), moxi = guess_ab_col(), - nali = guess_ab_col(), neom = guess_ab_col(), - neti = guess_ab_col(), nitr = guess_ab_col(), - norf = guess_ab_col(), novo = guess_ab_col(), - oflo = guess_ab_col(), oxac = guess_ab_col(), - peni = guess_ab_col(), pipe = guess_ab_col(), - pita = guess_ab_col(), poly = guess_ab_col(), - pris = guess_ab_col(), qida = guess_ab_col(), - rifa = guess_ab_col(), roxi = guess_ab_col(), - siso = guess_ab_col(), teic = guess_ab_col(), - tetr = guess_ab_col(), tica = guess_ab_col(), - tige = guess_ab_col(), tobr = guess_ab_col(), - trim = guess_ab_col(), trsu = guess_ab_col(), - vanc = guess_ab_col()) +eucast_rules(x, col_mo = NULL, info = TRUE, rules = c("breakpoints", + "expert", "other", "all"), verbose = FALSE, amcl = guess_ab_col(), + amik = guess_ab_col(), amox = guess_ab_col(), + ampi = guess_ab_col(), azit = guess_ab_col(), + azlo = guess_ab_col(), aztr = guess_ab_col(), + cefa = guess_ab_col(), cfep = guess_ab_col(), + cfot = guess_ab_col(), cfox = guess_ab_col(), + cfra = guess_ab_col(), cfta = guess_ab_col(), + cftr = guess_ab_col(), cfur = guess_ab_col(), + chlo = guess_ab_col(), cipr = guess_ab_col(), + clar = guess_ab_col(), clin = guess_ab_col(), + clox = guess_ab_col(), coli = guess_ab_col(), + czol = guess_ab_col(), dapt = guess_ab_col(), + doxy = guess_ab_col(), erta = guess_ab_col(), + eryt = guess_ab_col(), fosf = guess_ab_col(), + fusi = guess_ab_col(), gent = guess_ab_col(), + imip = guess_ab_col(), kana = guess_ab_col(), + levo = guess_ab_col(), linc = guess_ab_col(), + line = guess_ab_col(), mero = guess_ab_col(), + mezl = guess_ab_col(), mino = guess_ab_col(), + moxi = guess_ab_col(), nali = guess_ab_col(), + neom = guess_ab_col(), neti = guess_ab_col(), + nitr = guess_ab_col(), norf = guess_ab_col(), + novo = guess_ab_col(), oflo = guess_ab_col(), + oxac = guess_ab_col(), peni = guess_ab_col(), + pipe = guess_ab_col(), pita = guess_ab_col(), + poly = guess_ab_col(), pris = guess_ab_col(), + qida = guess_ab_col(), rifa = guess_ab_col(), + roxi = guess_ab_col(), siso = guess_ab_col(), + teic = guess_ab_col(), tetr = guess_ab_col(), + tica = guess_ab_col(), tige = guess_ab_col(), + tobr = guess_ab_col(), trim = guess_ab_col(), + trsu = guess_ab_col(), vanc = guess_ab_col(), ...) -EUCAST_rules(...) - -interpretive_reading(...)+eucast_rules_file()
tbl | -table with antibiotic columns, like e.g. |
+ x | +data with antibiotic columns, like e.g. |
---|---|---|---|
col_mo | @@ -324,10 +321,18 @@|||
- + | EUCAST rules |
||
-
|
Deprecated functions |