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

atc and bactid functions, readme update

This commit is contained in:
dr. M.S. (Matthijs) Berends 2018-08-25 22:01:14 +02:00
parent 460dee789f
commit 2acdb1981c
30 changed files with 761 additions and 449 deletions

View File

@ -1,5 +1,5 @@
Package: AMR Package: AMR
Version: 0.3.0.9003 Version: 0.3.0.9004
Date: 2018-08-23 Date: 2018-08-23
Title: Antimicrobial Resistance Analysis Title: Antimicrobial Resistance Analysis
Authors@R: c( Authors@R: c(

View File

@ -1,5 +1,6 @@
# Generated by roxygen2: do not edit by hand # Generated by roxygen2: do not edit by hand
S3method(as.data.frame,atc)
S3method(as.data.frame,bactid) S3method(as.data.frame,bactid)
S3method(as.data.frame,frequency_tbl) S3method(as.data.frame,frequency_tbl)
S3method(as.double,mic) S3method(as.double,mic)
@ -17,10 +18,12 @@ S3method(kurtosis,matrix)
S3method(plot,frequency_tbl) S3method(plot,frequency_tbl)
S3method(plot,mic) S3method(plot,mic)
S3method(plot,rsi) S3method(plot,rsi)
S3method(print,atc)
S3method(print,bactid) S3method(print,bactid)
S3method(print,frequency_tbl) S3method(print,frequency_tbl)
S3method(print,mic) S3method(print,mic)
S3method(print,rsi) S3method(print,rsi)
S3method(pull,atc)
S3method(pull,bactid) S3method(pull,bactid)
S3method(skewness,data.frame) S3method(skewness,data.frame)
S3method(skewness,default) S3method(skewness,default)
@ -35,12 +38,28 @@ export(MDRO)
export(MRGN) export(MRGN)
export(abname) export(abname)
export(anti_join_microorganisms) export(anti_join_microorganisms)
export(as.atc)
export(as.bactid) export(as.bactid)
export(as.mic) export(as.mic)
export(as.rsi) export(as.rsi)
export(atc.certe)
export(atc.official)
export(atc.official_nl)
export(atc.trivial_nl)
export(atc.umcg)
export(atc_ddd) export(atc_ddd)
export(atc_groups) export(atc_groups)
export(atc_property) export(atc_property)
export(bactid.aerobic)
export(bactid.family)
export(bactid.fullname)
export(bactid.genus)
export(bactid.gramstain)
export(bactid.gramstain_nl)
export(bactid.species)
export(bactid.subspecies)
export(bactid.type)
export(bactid.type_nl)
export(clipboard_export) export(clipboard_export)
export(clipboard_import) export(clipboard_import)
export(count_I) export(count_I)
@ -61,6 +80,7 @@ export(guess_atc)
export(guess_bactid) export(guess_bactid)
export(inner_join_microorganisms) export(inner_join_microorganisms)
export(interpretive_reading) export(interpretive_reading)
export(is.atc)
export(is.bactid) export(is.bactid)
export(is.mic) export(is.mic)
export(is.rsi) export(is.rsi)
@ -70,7 +90,6 @@ export(key_antibiotics_equal)
export(kurtosis) export(kurtosis)
export(left_join_microorganisms) export(left_join_microorganisms)
export(like) export(like)
export(mo_property)
export(n_rsi) export(n_rsi)
export(p.symbol) export(p.symbol)
export(portion_I) export(portion_I)
@ -89,6 +108,7 @@ export(semi_join_microorganisms)
export(skewness) export(skewness)
export(theme_rsi) export(theme_rsi)
export(top_freq) export(top_freq)
exportMethods(as.data.frame.atc)
exportMethods(as.data.frame.bactid) exportMethods(as.data.frame.bactid)
exportMethods(as.data.frame.frequency_tbl) exportMethods(as.data.frame.frequency_tbl)
exportMethods(as.double.mic) exportMethods(as.double.mic)
@ -107,10 +127,12 @@ exportMethods(kurtosis.matrix)
exportMethods(plot.frequency_tbl) exportMethods(plot.frequency_tbl)
exportMethods(plot.mic) exportMethods(plot.mic)
exportMethods(plot.rsi) exportMethods(plot.rsi)
exportMethods(print.atc)
exportMethods(print.bactid) exportMethods(print.bactid)
exportMethods(print.frequency_tbl) exportMethods(print.frequency_tbl)
exportMethods(print.mic) exportMethods(print.mic)
exportMethods(print.rsi) exportMethods(print.rsi)
exportMethods(pull.atc)
exportMethods(pull.bactid) exportMethods(pull.bactid)
exportMethods(skewness) exportMethods(skewness)
exportMethods(skewness.data.frame) exportMethods(skewness.data.frame)

View File

@ -4,6 +4,8 @@
* Functions `count_R`, `count_IR`, `count_I`, `count_SI` and `count_S` to selectively count resistant or susceptible isolates * Functions `count_R`, `count_IR`, `count_I`, `count_SI` and `count_S` to selectively count resistant or susceptible isolates
* New function `count_df` to get all counts of S, I and R of a data set with antibiotic columns, with support for grouped variables * New function `count_df` to get all counts of S, I and R of a data set with antibiotic columns, with support for grouped variables
* Function `is.rsi.eligible` to check for columns that have valid antimicrobial results, but do not have the `rsi` class yet. Transform the columns of your raw data with: `data %>% mutate_if(is.rsi.eligible, as.rsi)` * Function `is.rsi.eligible` to check for columns that have valid antimicrobial results, but do not have the `rsi` class yet. Transform the columns of your raw data with: `data %>% mutate_if(is.rsi.eligible, as.rsi)`
* Functions `as.atc` and `is.atc` to transform/look up antibiotic ATC codes as defined by the WHO. The existing function `guess_atc` is now an alias of `as.atc`.
* Function `mo_property` removed in favour of functions `bactid.family`, `bactid.genus`, `bactid.species`, `bactid.subspecies`, `bactid.fullname`, `bactid.type`, `bactid.gramstain`, `bactid.aerobic` to get a property of a microorganism based on their 'bactid'.
#### Changed #### Changed
* Removed function `ratio` * Removed function `ratio`

View File

@ -18,9 +18,9 @@
#' Name of an antibiotic #' Name of an antibiotic
#' #'
#' Convert antibiotic codes (from a laboratory information system like MOLIS or GLIMS) to a (trivial) antibiotic name or ATC code, or vice versa. This uses the data from \code{\link{antibiotics}}. #' Convert antibiotic codes to a (trivial) antibiotic name or ATC code, or vice versa. This uses the data from \code{\link{antibiotics}}.
#' @param abcode a code or name, like \code{"AMOX"}, \code{"AMCL"} or \code{"J01CA04"} #' @param abcode a code or name, like \code{"AMOX"}, \code{"AMCL"} or \code{"J01CA04"}
#' @param from,to type to transform from and to. See \code{\link{antibiotics}} for its column names. WIth \code{from = "guess"} the from will be guessed from \code{"atc"}, \code{"molis"} and \code{"umcg"}. When using \code{to = "atc"}, the ATC code will be searched using \code{\link{guess_atc}}. #' @param from,to type to transform from and to. See \code{\link{antibiotics}} for its column names. WIth \code{from = "guess"} the from will be guessed from \code{"atc"}, \code{"certe"} and \code{"umcg"}. When using \code{to = "atc"}, the ATC code will be searched using \code{\link{as.atc}}.
#' @param textbetween text to put between multiple returned texts #' @param textbetween text to put between multiple returned texts
#' @param tolower return output as lower case with function \code{\link{tolower}}. #' @param tolower return output as lower case with function \code{\link{tolower}}.
#' @keywords ab antibiotics #' @keywords ab antibiotics
@ -29,7 +29,7 @@
#' @importFrom dplyr %>% pull #' @importFrom dplyr %>% pull
#' @examples #' @examples
#' abname("AMCL") #' abname("AMCL")
#' # "amoxicillin and enzyme inhibitor" #' # "Amoxicillin and beta-lactamase inhibitor"
#' #'
#' # It is quite flexible at default (having `from = "guess"`) #' # It is quite flexible at default (having `from = "guess"`)
#' abname(c("amox", "J01CA04", "Trimox", "dispermox", "Amoxil")) #' abname(c("amox", "J01CA04", "Trimox", "dispermox", "Amoxil"))
@ -52,8 +52,12 @@
#' # specific codes for University Medical Center Groningen (UMCG): #' # specific codes for University Medical Center Groningen (UMCG):
#' abname("J01CR02", from = "atc", to = "umcg") #' abname("J01CR02", from = "atc", to = "umcg")
#' # "AMCL" #' # "AMCL"
#'
#' # specific codes for Certe:
#' abname("J01CR02", from = "atc", to = "certe")
#' # "amcl"
abname <- function(abcode, abname <- function(abcode,
from = c("guess", "atc", "molis", "umcg"), from = c("guess", "atc", "certe", "umcg"),
to = 'official', to = 'official',
textbetween = ' + ', textbetween = ' + ',
tolower = FALSE) { tolower = FALSE) {
@ -63,24 +67,12 @@ abname <- function(abcode,
} }
if (to == "atc") { if (to == "atc") {
return(guess_atc(abcode)) return(as.character(as.atc(abcode)))
} }
#antibiotics <- AMR::antibiotics
abx <- AMR::antibiotics abx <- AMR::antibiotics
from <- from[1] from <- from[1]
# if (from == "guess") {
# for (i in 1:3) {
# if (abcode[1] %in% (antibiotics %>% pull(i))) {
# from <- colnames(antibiotics)[i]
# }
# }
# if (from == "guess") {
# from <- "umcg"
# }
# }
colnames(abx) <- colnames(abx) %>% tolower() colnames(abx) <- colnames(abx) %>% tolower()
from <- from %>% tolower() from <- from %>% tolower()
to <- to %>% tolower() to <- to %>% tolower()
@ -112,9 +104,9 @@ abname <- function(abcode,
next next
} }
} }
if (from %in% c("molis", "guess")) { if (from %in% c("certe", "guess")) {
if (abcode[i] %in% abx$molis) { if (abcode[i] %in% abx$certe) {
abcode[i] <- abx[which(abx$molis == abcode[i]),] %>% pull(to) abcode[i] <- abx[which(abx$certe == abcode[i]),] %>% pull(to)
next next
} }
} }

263
R/atc.R
View File

@ -16,6 +16,185 @@
# GNU General Public License for more details. # # GNU General Public License for more details. #
# ==================================================================== # # ==================================================================== #
#' Find ATC code based on antibiotic property
#'
#' Use this function to determine the ATC code of one or more antibiotics. The dataset \code{\link{antibiotics}} will be searched for abbreviations, official names and trade names.
#' @param x character vector to determine \code{ATC} code
#' @rdname as.atc
#' @aliases atc
#' @keywords atc
#' @export
#' @importFrom dplyr %>% filter slice pull
#' @details In the ATC classification system, the active substances are classified in a hierarchy with five different levels. The system has fourteen main anatomical/pharmacological groups or 1st levels. Each ATC main group is divided into 2nd levels which could be either pharmacological or therapeutic groups. The 3rd and 4th levels are chemical, pharmacological or therapeutic subgroups and the 5th level is the chemical substance. The 2nd, 3rd and 4th levels are often used to identify pharmacological subgroups when that is considered more appropriate than therapeutic or chemical subgroups.
#' Source: \url{https://www.whocc.no/atc/structure_and_principles/}
#' @return Character (vector) with class \code{"act"}. Unknown values will return \code{NA}.
#' @seealso \code{\link{antibiotics}} for the dataframe that is being used to determine ATC's.
#' @examples
#' # These examples all return "J01FA01", the ATC code of Erythromycin:
#' as.atc("J01FA01")
#' as.atc("Erythromycin")
#' as.atc("eryt")
#' as.atc("ERYT")
#' as.atc("ERY")
#' as.atc("Erythrocin") # Trade name
#' as.atc("Eryzole") # Trade name
#' as.atc("Pediamycin") # Trade name
as.atc <- function(x) {
x.new <- rep(NA_character_, length(x))
x.bak <- x
x <- unique(x[!is.na(x)])
failures <- character(0)
for (i in 1:length(x)) {
fail <- TRUE
# first try atc
found <- AMR::antibiotics[which(AMR::antibiotics$atc == x[i]),]$atc
if (length(found) > 0) {
fail <- FALSE
x.new[is.na(x.new) & x.bak == x[i]] <- found[1L]
}
# try abbreviation of certe and glims
found <- AMR::antibiotics[which(tolower(AMR::antibiotics$certe) == tolower(x[i])),]$atc
if (length(found) > 0) {
fail <- FALSE
x.new[is.na(x.new) & x.bak == x[i]] <- found[1L]
}
found <- AMR::antibiotics[which(tolower(AMR::antibiotics$umcg) == tolower(x[i])),]$atc
if (length(found) > 0) {
fail <- FALSE
x.new[is.na(x.new) & x.bak == x[i]] <- found[1L]
}
# try exact official name
found <- AMR::antibiotics[which(tolower(AMR::antibiotics$official) == tolower(x[i])),]$atc
if (length(found) > 0) {
fail <- FALSE
x.new[is.na(x.new) & x.bak == x[i]] <- found[1L]
}
# try trade name
found <- AMR::antibiotics[which(paste0("(", AMR::antibiotics$trade_name, ")") %like% x[i]),]$atc
if (length(found) > 0) {
fail <- FALSE
x.new[is.na(x.new) & x.bak == x[i]] <- found[1L]
}
# try abbreviation
found <- AMR::antibiotics[which(paste0("(", AMR::antibiotics$abbr, ")") %like% x[i]),]$atc
if (length(found) > 0) {
fail <- FALSE
x.new[is.na(x.new) & x.bak == x[i]] <- found[1L]
}
# not found
if (fail == TRUE) {
failures <- c(failures, x[i])
}
}
failures <- failures[!failures %in% c(NA, NULL, NaN)]
if (length(failures) > 0) {
warning("These values could not be coerced to a valid atc: ",
paste('"', unique(failures), '"', sep = "", collapse = ', '),
".",
call. = FALSE)
}
class(x.new) <- "atc"
attr(x.new, 'package') <- 'AMR'
x.new
}
#' @rdname as.atc
#' @export
guess_atc <- as.atc
#' @rdname as.atc
#' @export
is.atc <- function(x) {
identical(class(x), "atc")
}
#' @exportMethod print.atc
#' @export
#' @noRd
print.atc <- function(x, ...) {
cat("Class 'atc'\n")
print.default(as.character(x), quote = FALSE)
}
#' @exportMethod as.data.frame.atc
#' @export
#' @noRd
as.data.frame.atc <- function (x, ...) {
# same as as.data.frame.character but with removed stringsAsFactors
nm <- paste(deparse(substitute(x), width.cutoff = 500L),
collapse = " ")
if (!"nm" %in% names(list(...))) {
as.data.frame.vector(x, ..., nm = nm)
} else {
as.data.frame.vector(x, ...)
}
}
#' @exportMethod pull.atc
#' @export
#' @importFrom dplyr pull
#' @noRd
pull.atc <- function(.data, ...) {
pull(as.data.frame(.data), ...)
}
atc_get_property <- function(atc, param) {
if (!is.atc(atc)) {
atc <- as.atc(atc)
}
suppressWarnings(
data.frame(atc = atc, stringsAsFactors = FALSE) %>%
left_join(AMR::antibiotics, by = "atc") %>%
pull(param)
)
}
#' Get antibiotic property based on ATC
#'
#' Use these functions to return a specific property of an antibiotic from the \code{\link{antibiotics}} data set, based on their ATC code.
#' @param atc a valid ATC code, created with \code{\link{as.atc}}
#' @rdname atc.property
#' @name atc.property
#' @export
atc.official <- function(atc) {
atc_get_property(atc, "official")
}
#' @rdname atc.property
#' @export
atc.official_nl <- function(atc) {
atc_get_property(atc, "official_nl")
}
#' @rdname atc.property
#' @export
atc.trivial_nl <- function(atc) {
atc_get_property(atc, "trivial_nl")
}
#' @rdname atc.property
#' @export
atc.certe <- function(atc) {
atc_get_property(atc, "certe")
}
#' @rdname atc.property
#' @export
atc.umcg <- function(atc) {
atc_get_property(atc, "umcg")
}
#' Properties of an ATC code #' Properties of an ATC code
#' #'
#' Gets data from the WHO to determine properties of an ATC (e.g. an antibiotic) like name, defined daily dose (DDD) or standard unit. \cr \strong{This function requires an internet connection.} #' Gets data from the WHO to determine properties of an ATC (e.g. an antibiotic) like name, defined daily dose (DDD) or standard unit. \cr \strong{This function requires an internet connection.}
@ -203,87 +382,3 @@ atc_ddd <- function(atc_code, ...) {
atc_property(atc_code = atc_code, property = "ddd", ...) atc_property(atc_code = atc_code, property = "ddd", ...)
} }
#' Find ATC code based on antibiotic property
#'
#' Use this function to determine the ATC code of one or more antibiotics. The dataset \code{\link{antibiotics}} will be searched for abbreviations, official names and trade names.
#' @param x character vector to determine \code{ATC} code
#' @export
#' @importFrom dplyr %>% filter slice pull
#' @details In the ATC classification system, the active substances are classified in a hierarchy with five different levels. The system has fourteen main anatomical/pharmacological groups or 1st levels. Each ATC main group is divided into 2nd levels which could be either pharmacological or therapeutic groups. The 3rd and 4th levels are chemical, pharmacological or therapeutic subgroups and the 5th level is the chemical substance. The 2nd, 3rd and 4th levels are often used to identify pharmacological subgroups when that is considered more appropriate than therapeutic or chemical subgroups.
#' Source: \url{https://www.whocc.no/atc/structure_and_principles/}
#' @return Character (vector).
#' @seealso \code{\link{antibiotics}} for the dataframe that is being used to determine ATC's.
#' @examples
#' # These examples all return "J01FA01", the ATC code of Erythromycin:
#' guess_atc("J01FA01")
#' guess_atc("Erythromycin")
#' guess_atc("eryt")
#' guess_atc("ERYT")
#' guess_atc("ERY")
#' guess_atc("Erythrocin") # Trade name
#' guess_atc("Eryzole") # Trade name
#' guess_atc("Pediamycin") # Trade name
guess_atc <- function(x) {
# use this later to further fill AMR::antibiotics
# drug <- "Ciprofloxacin"
# url <- xml2::read_html(paste0("https://www.ncbi.nlm.nih.gov/pccompound?term=", drug)) %>%
# html_nodes(".rslt") %>%
# .[[1]] %>%
# html_nodes(".title a") %>%
# html_attr("href") %>%
# gsub("/compound/", "/rest/pug_view/data/compound/", ., fixed = TRUE) %>%
# paste0("/XML/?response_type=display")
# synonyms <- url %>%
# read_xml() %>%
# xml_contents() %>% .[[6]] %>%
# xml_contents() %>% .[[8]] %>%
# xml_contents() %>% .[[3]] %>%
# xml_contents() %>% .[[3]] %>%
# xml_contents() %>%
# paste() %>%
# .[. %like% "StringValueList"] %>%
# gsub("[</]+StringValueList[>]", "", .)
for (i in 1:length(x)) {
# first try atc
found <- AMR::antibiotics %>% filter(atc == x[i])
if (nrow(found) == 0) {
# try abbreviation of molis and glims
found <- AMR::antibiotics %>% filter(tolower(molis) == tolower(x[i]) | tolower(umcg) == tolower(x[i]))
}
if (nrow(found) == 0) {
# try exact official name
found <- AMR::antibiotics[which(tolower(AMR::antibiotics$official) == tolower(x[i])),]
}
if (nrow(found) == 0) {
# try trade name
found <- AMR::antibiotics[which(paste0("(", AMR::antibiotics$trade_name, ")") %like% x[i]),]
}
if (nrow(found) == 0) {
# try abbreviation
found <- AMR::antibiotics[which(paste0("(", AMR::antibiotics$abbr, ")") %like% x[i]),]
}
# if (nrow(found) == 0) {
# # loosely try official name
# found <- AMR::antibiotics[which(AMR::antibiotics$official %like% x[i]),]
# }
if (nrow(found) != 0) {
x[i] <- found %>%
slice(1) %>%
pull(atc)
} else {
x[i] <- NA
}
}
x
}

View File

@ -380,3 +380,79 @@ as.data.frame.bactid <- function (x, ...) {
pull.bactid <- function(.data, ...) { pull.bactid <- function(.data, ...) {
pull(as.data.frame(.data), ...) pull(as.data.frame(.data), ...)
} }
bactid_get_property <- function(bactid, param) {
if (!is.bactid(bactid)) {
bactid <- as.bactid(bactid)
}
suppressWarnings(
data.frame(bactid = bactid, stringsAsFactors = FALSE) %>%
left_join(AMR::microorganisms, by = "bactid") %>%
pull(param)
)
}
#' Get microbial property based on `bactid`
#'
#' Use these functions to return a specific property of a microorganism from the \code{\link{microorganisms}} data set, based on their \code{bactid}. Get such an ID with \code{\link{as.bactid}}.
#' @param bactid a valid bactid code, created with \code{\link{as.bactid}}
#' @rdname bactid.property
#' @name bactid.property
#' @export
bactid.family <- function(bactid) {
bactid_get_property(bactid, "family")
}
#' @rdname bactid.property
#' @export
bactid.genus <- function(bactid) {
bactid_get_property(bactid, "genus")
}
#' @rdname bactid.property
#' @export
bactid.species <- function(bactid) {
bactid_get_property(bactid, "species")
}
#' @rdname bactid.property
#' @export
bactid.subspecies <- function(bactid) {
bactid_get_property(bactid, "subspecies")
}
#' @rdname bactid.property
#' @export
bactid.fullname <- function(bactid) {
bactid_get_property(bactid, "fullname")
}
#' @rdname bactid.property
#' @export
bactid.type <- function(bactid) {
bactid_get_property(bactid, "type")
}
#' @rdname bactid.property
#' @export
bactid.gramstain <- function(bactid) {
bactid_get_property(bactid, "gramstain")
}
#' @rdname bactid.property
#' @export
bactid.aerobic <- function(bactid) {
bactid_get_property(bactid, "aerobic")
}
#' @rdname bactid.property
#' @export
bactid.type_nl <- function(bactid) {
bactid_get_property(bactid, "type_nl")
}
#' @rdname bactid.property
#' @export
bactid.gramstain_nl <- function(bactid) {
bactid_get_property(bactid, "gramstain_nl")
}

View File

@ -22,7 +22,7 @@
#' @format A data.frame with 420 observations and 18 variables: #' @format A data.frame with 420 observations and 18 variables:
#' \describe{ #' \describe{
#' \item{\code{atc}}{ATC code, like \code{J01CR02}} #' \item{\code{atc}}{ATC code, like \code{J01CR02}}
#' \item{\code{molis}}{MOLIS code, like \code{amcl}} #' \item{\code{certe}}{Certe code, like \code{amcl}}
#' \item{\code{umcg}}{UMCG code, like \code{AMCL}} #' \item{\code{umcg}}{UMCG code, like \code{AMCL}}
#' \item{\code{abbr}}{Abbreviation as used by many countries, to be used for \code{\link{guess_atc}}} #' \item{\code{abbr}}{Abbreviation as used by many countries, to be used for \code{\link{guess_atc}}}
#' \item{\code{official}}{Official name by the WHO, like \code{"Amoxicillin and enzyme inhibitor"}} #' \item{\code{official}}{Official name by the WHO, like \code{"Amoxicillin and enzyme inhibitor"}}
@ -42,6 +42,25 @@
#' } #' }
#' @source - World Health Organization: \url{https://www.whocc.no/atc_ddd_index/} \cr - EUCAST - Expert rules intrinsic exceptional V3.1 \cr - MOLIS (LIS of Certe): \url{https://www.certe.nl} \cr - GLIMS (LIS of UMCG): \url{https://www.umcg.nl} #' @source - World Health Organization: \url{https://www.whocc.no/atc_ddd_index/} \cr - EUCAST - Expert rules intrinsic exceptional V3.1 \cr - MOLIS (LIS of Certe): \url{https://www.certe.nl} \cr - GLIMS (LIS of UMCG): \url{https://www.umcg.nl}
#' @seealso \code{\link{microorganisms}} #' @seealso \code{\link{microorganisms}}
# use this later to further fill AMR::antibiotics
# drug <- "Ciprofloxacin"
# url <- xml2::read_html(paste0("https://www.ncbi.nlm.nih.gov/pccompound?term=", drug)) %>%
# html_nodes(".rslt") %>%
# .[[1]] %>%
# html_nodes(".title a") %>%
# html_attr("href") %>%
# gsub("/compound/", "/rest/pug_view/data/compound/", ., fixed = TRUE) %>%
# paste0("/XML/?response_type=display")
# synonyms <- url %>%
# read_xml() %>%
# xml_contents() %>% .[[6]] %>%
# xml_contents() %>% .[[8]] %>%
# xml_contents() %>% .[[3]] %>%
# xml_contents() %>% .[[3]] %>%
# xml_contents() %>%
# paste() %>%
# .[. %like% "StringValueList"] %>%
# gsub("[</]+StringValueList[>]", "", .)
# abbr and trade_name created with: # abbr and trade_name created with:
# https://hs.unr.edu/Documents/dhs/chs/NVPHTC/antibiotic_refeference_guide.pdf # https://hs.unr.edu/Documents/dhs/chs/NVPHTC/antibiotic_refeference_guide.pdf
# antibiotics %>% # antibiotics %>%

View File

@ -695,38 +695,3 @@ EUCAST_rules <- function(tbl,
interpretive_reading <- function(...) { interpretive_reading <- function(...) {
EUCAST_rules(...) EUCAST_rules(...)
} }
#' Poperties of a microorganism
#'
#' @param bactid ID of a microorganisme, like \code{"STAAUR} and \code{"ESCCOL}
#' @param property One of the values \code{bactid}, \code{bactsys}, \code{family}, \code{genus}, \code{species}, \code{subspecies}, \code{fullname}, \code{type}, \code{gramstain}, \code{aerobic}
#' @export
#' @importFrom dplyr %>% filter select
#' @seealso \code{\link{microorganisms}}
mo_property <- function(bactid, property = 'fullname') {
mocode <- as.character(bactid)
for (i in 1:length(mocode)) {
bug <- mocode[i]
if (!is.na(bug)) {
result = tryCatch({
mocode[i] <-
AMR::microorganisms %>%
filter(bactid == bug) %>%
select(property) %>%
unlist() %>%
as.character()
}, error = function(error_condition) {
warning('Code ', bug, ' not found in bacteria list.')
}, finally = {
if (mocode[i] == bug & !property %in% c('bactid', 'bactsys')) {
mocode[i] <- NA
}
})
}
}
mocode
}

View File

@ -30,6 +30,7 @@ globalVariables(c('abname',
'atc', 'atc',
'bactid', 'bactid',
'C_chisq_sim', 'C_chisq_sim',
'certe',
'cnt', 'cnt',
'count', 'count',
'Count', 'Count',
@ -54,7 +55,6 @@ globalVariables(c('abname',
'MIC', 'MIC',
'microorganisms', 'microorganisms',
'mocode', 'mocode',
'molis',
'n', 'n',
'na.omit', 'na.omit',
'observations', 'observations',

View File

@ -16,186 +16,6 @@
# GNU General Public License for more details. # # GNU General Public License for more details. #
# ==================================================================== # # ==================================================================== #
#' Class 'rsi'
#'
#' This transforms a vector to a new class \code{rsi}, which is an ordered factor with levels \code{S < I < R}. Invalid antimicrobial interpretations will be translated as \code{NA} with a warning.
#' @rdname as.rsi
#' @param x vector
#' @details The function \code{is.rsi.eligible} returns \code{TRUE} when a columns contains only valid antimicrobial interpretations (S and/or I and/or R), and \code{FALSE} otherwise.
#' @return Ordered factor with new class \code{rsi} and new attribute \code{package}
#' @keywords rsi
#' @export
#' @importFrom dplyr %>%
#' @seealso \code{\link{as.mic}}
#' @examples
#' rsi_data <- as.rsi(c(rep("S", 474), rep("I", 36), rep("R", 370)))
#' rsi_data <- as.rsi(c(rep("S", 474), rep("I", 36), rep("R", 370), "A", "B", "C"))
#' is.rsi(rsi_data)
#'
#' # this can also coerce combined MIC/RSI values:
#' as.rsi("<= 0.002; S") # will return S
#'
#' plot(rsi_data) # for percentages
#' barplot(rsi_data) # for frequencies
#' freq(rsi_data) # frequency table with informative header
#'
#' # fastest way to transform all columns with already valid AB results to class `rsi`:
#' library(dplyr)
#' septic_patients %>%
#' mutate_if(is.rsi.eligible,
#' as.rsi)
as.rsi <- function(x) {
if (is.rsi(x)) {
x
} else {
x <- x %>% unlist()
x.bak <- x
na_before <- x[is.na(x) | x == ''] %>% length()
# remove all spaces
x <- gsub(' +', '', x)
# remove all MIC-like values: numbers, operators and periods
x <- gsub('[0-9.,;:<=>]+', '', x)
# disallow more than 3 characters
x[nchar(x) > 3] <- NA
# set to capitals
x <- toupper(x)
# remove all invalid characters
x <- gsub('[^RSI]+', '', x)
# in cases of "S;S" keep S, but in case of "S;I" make it NA
x <- gsub('^S+$', 'S', x)
x <- gsub('^I+$', 'I', x)
x <- gsub('^R+$', 'R', x)
x[!x %in% c('S', 'I', 'R')] <- NA
na_after <- x[is.na(x) | x == ''] %>% length()
if (na_before != na_after) {
list_missing <- x.bak[is.na(x) & !is.na(x.bak) & x.bak != ''] %>%
unique() %>%
sort()
list_missing <- paste0('"', list_missing , '"', collapse = ", ")
warning(na_after - na_before, ' results truncated (',
round(((na_after - na_before) / length(x)) * 100),
'%) that were invalid antimicrobial interpretations: ',
list_missing, call. = FALSE)
}
x <- x %>% factor(levels = c("S", "I", "R"), ordered = TRUE)
class(x) <- c('rsi', 'ordered', 'factor')
attr(x, 'package') <- 'AMR'
x
}
}
#' @rdname as.rsi
#' @export
#' @importFrom dplyr %>%
is.rsi <- function(x) {
class(x) %>% identical(c('rsi', 'ordered', 'factor'))
}
#' @rdname as.rsi
#' @export
#' @importFrom dplyr %>%
is.rsi.eligible <- function(x) {
distinct_val <- x %>% unique() %>% sort() %>% as.character()
distinct_val <- distinct_val[!is.na(distinct_val) & trimws(distinct_val) != ""]
distinct_val_rsi <- as.character(suppressWarnings(as.rsi(distinct_val)))
length(distinct_val) > 0 &
identical(distinct_val, distinct_val_rsi)
}
#' @exportMethod print.rsi
#' @export
#' @importFrom dplyr %>%
#' @noRd
print.rsi <- function(x, ...) {
cat("Class 'rsi'\n")
print(as.character(x), quote = FALSE)
}
#' @exportMethod summary.rsi
#' @export
#' @noRd
summary.rsi <- function(object, ...) {
x <- object
c(
"Mode" = 'rsi',
"<NA>" = sum(is.na(x)),
"Sum S" = sum(x == "S", na.rm = TRUE),
"Sum IR" = sum(x %in% c("I", "R"), na.rm = TRUE),
"-Sum R" = sum(x == "R", na.rm = TRUE),
"-Sum I" = sum(x == "I", na.rm = TRUE)
)
}
#' @exportMethod plot.rsi
#' @export
#' @importFrom dplyr %>% group_by summarise filter mutate if_else n_distinct
#' @importFrom graphics plot text
#' @noRd
plot.rsi <- function(x, ...) {
x_name <- deparse(substitute(x))
data <- data.frame(x = x,
y = 1,
stringsAsFactors = TRUE) %>%
group_by(x) %>%
summarise(n = sum(y)) %>%
filter(!is.na(x)) %>%
mutate(s = round((n / sum(n)) * 100, 1))
data$x <- factor(data$x, levels = c('S', 'I', 'R'), ordered = TRUE)
ymax <- if_else(max(data$s) > 95, 105, 100)
plot(x = data$x,
y = data$s,
lwd = 2,
col = c('green', 'orange', 'red'),
ylim = c(0, ymax),
ylab = 'Percentage',
xlab = 'Antimicrobial Interpretation',
main = paste('Susceptibility Analysis of', x_name),
axes = FALSE,
...)
# x axis
axis(side = 1, at = 1:n_distinct(data$x), labels = levels(data$x), lwd = 0)
# y axis, 0-100%
axis(side = 2, at = seq(0, 100, 5))
text(x = data$x,
y = data$s + 4,
labels = paste0(data$s, '% (n = ', data$n, ')'))
}
#' @exportMethod barplot.rsi
#' @export
#' @importFrom dplyr %>% group_by summarise filter mutate if_else n_distinct
#' @importFrom graphics barplot axis
#' @noRd
barplot.rsi <- function(height, ...) {
x <- height
x_name <- deparse(substitute(height))
data <- data.frame(rsi = x, cnt = 1) %>%
group_by(rsi) %>%
summarise(cnt = sum(cnt)) %>%
droplevels()
barplot(table(x),
col = c('green3', 'orange2', 'red3'),
xlab = 'Antimicrobial Interpretation',
main = paste('Susceptibility Analysis of', x_name),
ylab = 'Frequency',
axes = FALSE,
...)
# y axis, 0-100%
axis(side = 2, at = seq(0, max(data$cnt) + max(data$cnt) * 1.1, by = 25))
}
#' Class 'mic' #' Class 'mic'
#' #'
#' This transforms a vector to a new class \code{mic}, which is an ordered factor with valid MIC values as levels. Invalid MIC values will be translated as \code{NA} with a warning. #' This transforms a vector to a new class \code{mic}, which is an ordered factor with valid MIC values as levels. Invalid MIC values will be translated as \code{NA} with a warning.

View File

@ -251,3 +251,48 @@ portion_df <- function(data,
res res
} }
#' Calculate resistance of isolates
#'
#' This function is deprecated. Use the \code{\link{portion}} functions instead.
#' @inheritParams portion
#' @param ab1,ab2 vector (or column) with antibiotic interpretations. It will be transformed internally with \code{\link{as.rsi}} if needed.
#' @param interpretation antimicrobial interpretation to check for
#' @param ... deprecated parameters to support usage on older versions
#' @importFrom dplyr tibble case_when
#' @export
rsi <- function(ab1,
ab2 = NULL,
interpretation = "IR",
minimum = 30,
as_percent = FALSE,
...) {
if (all(is.null(ab2))) {
df <- tibble(ab1 = ab1)
} else {
df <- tibble(ab1 = ab1,
ab2 = ab2)
}
result <- case_when(
interpretation == "S" ~ portion_S(df, minimum = minimum, as_percent = FALSE),
interpretation %in% c("SI", "IS") ~ portion_SI(df, minimum = minimum, as_percent = FALSE),
interpretation == "I" ~ portion_I(df, minimum = minimum, as_percent = FALSE),
interpretation %in% c("RI", "IR") ~ portion_IR(df, minimum = minimum, as_percent = FALSE),
interpretation == "R" ~ portion_R(df, minimum = minimum, as_percent = FALSE),
TRUE ~ -1
)
if (result == -1) {
stop("invalid interpretation")
}
.Deprecated(new = paste0("portion_", interpretation))
if (as_percent == TRUE) {
percent(result, force_zero = TRUE)
} else {
result
}
}

208
R/rsi.R
View File

@ -16,46 +16,182 @@
# GNU General Public License for more details. # # GNU General Public License for more details. #
# ==================================================================== # # ==================================================================== #
#' Calculate resistance of isolates #' Class 'rsi'
#' #'
#' This function is deprecated. Use the \code{\link{portion}} functions instead. #' This transforms a vector to a new class \code{rsi}, which is an ordered factor with levels \code{S < I < R}. Invalid antimicrobial interpretations will be translated as \code{NA} with a warning.
#' @inheritParams portion #' @rdname as.rsi
#' @param ab1,ab2 vector (or column) with antibiotic interpretations. It will be transformed internally with \code{\link{as.rsi}} if needed. #' @param x vector
#' @param interpretation antimicrobial interpretation to check for #' @details The function \code{is.rsi.eligible} returns \code{TRUE} when a columns contains only valid antimicrobial interpretations (S and/or I and/or R), and \code{FALSE} otherwise.
#' @param ... deprecated parameters to support usage on older versions #' @return Ordered factor with new class \code{rsi} and new attribute \code{package}
#' @importFrom dplyr tibble case_when #' @keywords rsi
#' @export #' @export
rsi <- function(ab1, #' @importFrom dplyr %>%
ab2 = NULL, #' @seealso \code{\link{as.mic}}
interpretation = "IR", #' @examples
minimum = 30, #' rsi_data <- as.rsi(c(rep("S", 474), rep("I", 36), rep("R", 370)))
as_percent = FALSE, #' rsi_data <- as.rsi(c(rep("S", 474), rep("I", 36), rep("R", 370), "A", "B", "C"))
...) { #' is.rsi(rsi_data)
#'
if (all(is.null(ab2))) { #' # this can also coerce combined MIC/RSI values:
df <- tibble(ab1 = ab1) #' as.rsi("<= 0.002; S") # will return S
#'
#' plot(rsi_data) # for percentages
#' barplot(rsi_data) # for frequencies
#' freq(rsi_data) # frequency table with informative header
#'
#' # fastest way to transform all columns with already valid AB results to class `rsi`:
#' library(dplyr)
#' septic_patients %>%
#' mutate_if(is.rsi.eligible,
#' as.rsi)
as.rsi <- function(x) {
if (is.rsi(x)) {
x
} else { } else {
df <- tibble(ab1 = ab1,
ab2 = ab2) x <- x %>% unlist()
x.bak <- x
na_before <- x[is.na(x) | x == ''] %>% length()
# remove all spaces
x <- gsub(' +', '', x)
# remove all MIC-like values: numbers, operators and periods
x <- gsub('[0-9.,;:<=>]+', '', x)
# disallow more than 3 characters
x[nchar(x) > 3] <- NA
# set to capitals
x <- toupper(x)
# remove all invalid characters
x <- gsub('[^RSI]+', '', x)
# in cases of "S;S" keep S, but in case of "S;I" make it NA
x <- gsub('^S+$', 'S', x)
x <- gsub('^I+$', 'I', x)
x <- gsub('^R+$', 'R', x)
x[!x %in% c('S', 'I', 'R')] <- NA
na_after <- x[is.na(x) | x == ''] %>% length()
if (na_before != na_after) {
list_missing <- x.bak[is.na(x) & !is.na(x.bak) & x.bak != ''] %>%
unique() %>%
sort()
list_missing <- paste0('"', list_missing , '"', collapse = ", ")
warning(na_after - na_before, ' results truncated (',
round(((na_after - na_before) / length(x)) * 100),
'%) that were invalid antimicrobial interpretations: ',
list_missing, call. = FALSE)
} }
result <- case_when( x <- x %>% factor(levels = c("S", "I", "R"), ordered = TRUE)
interpretation == "S" ~ portion_S(df, minimum = minimum, as_percent = FALSE), class(x) <- c('rsi', 'ordered', 'factor')
interpretation %in% c("SI", "IS") ~ portion_SI(df, minimum = minimum, as_percent = FALSE), attr(x, 'package') <- 'AMR'
interpretation == "I" ~ portion_I(df, minimum = minimum, as_percent = FALSE), x
interpretation %in% c("RI", "IR") ~ portion_IR(df, minimum = minimum, as_percent = FALSE),
interpretation == "R" ~ portion_R(df, minimum = minimum, as_percent = FALSE),
TRUE ~ -1
)
if (result == -1) {
stop("invalid interpretation")
}
.Deprecated(new = paste0("portion_", interpretation))
if (as_percent == TRUE) {
percent(result, force_zero = TRUE)
} else {
result
} }
} }
#' @rdname as.rsi
#' @export
#' @importFrom dplyr %>%
is.rsi <- function(x) {
class(x) %>% identical(c('rsi', 'ordered', 'factor'))
}
#' @rdname as.rsi
#' @export
#' @importFrom dplyr %>%
is.rsi.eligible <- function(x) {
distinct_val <- x %>% unique() %>% sort() %>% as.character()
distinct_val <- distinct_val[!is.na(distinct_val) & trimws(distinct_val) != ""]
distinct_val_rsi <- as.character(suppressWarnings(as.rsi(distinct_val)))
length(distinct_val) > 0 &
identical(distinct_val, distinct_val_rsi)
}
#' @exportMethod print.rsi
#' @export
#' @importFrom dplyr %>%
#' @noRd
print.rsi <- function(x, ...) {
cat("Class 'rsi'\n")
print(as.character(x), quote = FALSE)
}
#' @exportMethod summary.rsi
#' @export
#' @noRd
summary.rsi <- function(object, ...) {
x <- object
c(
"Mode" = 'rsi',
"<NA>" = sum(is.na(x)),
"Sum S" = sum(x == "S", na.rm = TRUE),
"Sum IR" = sum(x %in% c("I", "R"), na.rm = TRUE),
"-Sum R" = sum(x == "R", na.rm = TRUE),
"-Sum I" = sum(x == "I", na.rm = TRUE)
)
}
#' @exportMethod plot.rsi
#' @export
#' @importFrom dplyr %>% group_by summarise filter mutate if_else n_distinct
#' @importFrom graphics plot text
#' @noRd
plot.rsi <- function(x, ...) {
x_name <- deparse(substitute(x))
data <- data.frame(x = x,
y = 1,
stringsAsFactors = TRUE) %>%
group_by(x) %>%
summarise(n = sum(y)) %>%
filter(!is.na(x)) %>%
mutate(s = round((n / sum(n)) * 100, 1))
data$x <- factor(data$x, levels = c('S', 'I', 'R'), ordered = TRUE)
ymax <- if_else(max(data$s) > 95, 105, 100)
plot(x = data$x,
y = data$s,
lwd = 2,
col = c('green', 'orange', 'red'),
ylim = c(0, ymax),
ylab = 'Percentage',
xlab = 'Antimicrobial Interpretation',
main = paste('Susceptibility Analysis of', x_name),
axes = FALSE,
...)
# x axis
axis(side = 1, at = 1:n_distinct(data$x), labels = levels(data$x), lwd = 0)
# y axis, 0-100%
axis(side = 2, at = seq(0, 100, 5))
text(x = data$x,
y = data$s + 4,
labels = paste0(data$s, '% (n = ', data$n, ')'))
}
#' @exportMethod barplot.rsi
#' @export
#' @importFrom dplyr %>% group_by summarise filter mutate if_else n_distinct
#' @importFrom graphics barplot axis
#' @noRd
barplot.rsi <- function(height, ...) {
x <- height
x_name <- deparse(substitute(height))
data <- data.frame(rsi = x, cnt = 1) %>%
group_by(rsi) %>%
summarise(cnt = sum(cnt)) %>%
droplevels()
barplot(table(x),
col = c('green3', 'orange2', 'red3'),
xlab = 'Antimicrobial Interpretation',
main = paste('Susceptibility Analysis of', x_name),
ylab = 'Frequency',
axes = FALSE,
...)
# y axis, 0-100%
axis(side = 2, at = seq(0, max(data$cnt) + max(data$cnt) * 1.1, by = 25))
}

View File

@ -3,7 +3,7 @@
This R package was created for academic research by PhD students of the Faculty of Medical Sciences of the [University of Groningen](https://www.rug.nl) and the Medical Microbiology & Infection Prevention (MMBI) department of the [University Medical Center Groningen (UMCG)](https://www.umcg.nl). This R package was created for academic research by PhD students of the Faculty of Medical Sciences of the [University of Groningen](https://www.rug.nl) and the Medical Microbiology & Infection Prevention (MMBI) department of the [University Medical Center Groningen (UMCG)](https://www.umcg.nl).
:arrow_forward: Download it with `install.packages("AMR")` or see below for other possibilities. :arrow_forward: Get it with `install.packages("AMR")` or see below for other possibilities. Read all changes and new functions in [NEWS.md](NEWS.md).
## Authors ## Authors
<a href="https://orcid.org/0000-0001-7620-1800"><img src="https://cran.r-project.org/web/orcid.svg" height="16px"></a> Matthijs S. Berends<sup>1,2,a</sup>, <a href="https://orcid.org/0000-0001-7620-1800"><img src="https://cran.r-project.org/web/orcid.svg" height="16px"></a> Matthijs S. Berends<sup>1,2,a</sup>,
@ -40,31 +40,31 @@ Erwin E.A. Hassing<sup>2</sup>,
## Why this package? ## Why this package?
This R package was intended to make microbial epidemiology easier. Most functions contain extensive help pages to get started. This R package was intended to make microbial epidemiology easier. Most functions contain extensive help pages to get started.
With `AMR` you can: This `AMR` package basically does four important things:
* Calculate the resistance (and even co-resistance) of microbial isolates with the `portion_R`, `portion_IR`, `portion_I`, `portion_SI` and `portion_S` functions, that can also be used with the `dplyr` package (e.g. in conjunction with `summarise`)
* Plot AMR results with `geom_rsi`, a function made for the `ggplot2` package
* Predict antimicrobial resistance for the nextcoming years using logistic regression models with the `resistance_predict` function
* Apply [EUCAST rules to isolates](http://www.eucast.org/expert_rules_and_intrinsic_resistance/) with the `EUCAST_rules` function
* Identify first isolates of every patient [using guidelines from the CLSI](https://clsi.org/standards/products/microbiology/documents/m39/) (Clinical and Laboratory Standards Institute) with the `first_isolate` function
* You can also identify first *weighted* isolates of every patient, an adjusted version of the CLSI guideline. This takes into account key antibiotics of every strain and compares them. The following 12 antibiotics will be used as key antibiotics at default:
* Universal: amoxicillin, amoxicillin/clavlanic acid, cefuroxime, piperacillin/tazobactam, ciprofloxacin, trimethoprim/sulfamethoxazole
* Specific for Gram-positives: vancomycin, teicoplanin, tetracycline, erythromycin, oxacillin, rifampicin
* Specific for Gram-negatives: gentamicin, tobramycin, colistin, cefotaxime, ceftazidime, meropenem
* Categorise *Staphylococci* into Coagulase Negative *Staphylococci* (CoNS) and Coagulase Positve *Staphylococci* (CoPS) according to [Karsten Becker *et al.*](https://www.ncbi.nlm.nih.gov/pmc/articles/pmid/25278577/)
* Categorise *Streptococci* into Lancefield groups
* Get antimicrobial ATC properties from the WHO Collaborating Centre for Drug Statistics Methodology ([WHOCC](https://www.whocc.no/atc_ddd_methodology/who_collaborating_centre/)), to be able to:
* Translate antibiotic codes (like *AMOX*), official names (like *amoxicillin*) and even trade names (like *Amoxil* or *Trimox*) to an [ATC code](https://www.whocc.no/atc_ddd_index/?code=J01CA04&showdescription=no) (like *J01CA04*) and vice versa with the `abname` function
* Get the latest antibiotic properties like hierarchic groups and [defined daily dose](https://en.wikipedia.org/wiki/Defined_daily_dose) (DDD) with units and administration form from the WHOCC website with the `atc_property` function
* Conduct descriptive statistics: calculate kurtosis, skewness and create frequency tables
And it contains: 1. It **cleanses existing data**, by transforming it to reproducible and profound *classes*, making the most efficient use of R. These function all use artificial intelligence to get expected results:
* A recent data set with ~2500 human pathogenic microorganisms, including family, genus, species, gram stain and aerobic/anaerobic
* A recent data set with all antibiotics as defined by the [WHOCC](https://www.whocc.no/atc_ddd_methodology/who_collaborating_centre/), including ATC code, official name and DDD's
* An example data set `septic_patients`, consisting of 2000 blood culture isolates from anonymised septic patients between 2001 and 2017.
With the `MDRO` function (abbreviation of Multi Drug Resistant Organisms), you can check your isolates for exceptional resistance with country-specific guidelines or EUCAST rules. Currently guidelines for Germany and the Netherlands are supported. Please suggest addition of your own country here: [https://github.com/msberends/AMR/issues/new](https://github.com/msberends/AMR/issues/new?title=New%20guideline%20for%20MDRO&body=%3C--%20Please%20add%20your%20country%20code,%20guideline%20name,%20version%20and%20source%20below%20and%20remove%20this%20line--%3E). * Use `as.bactid` to get an ID of a microorganism. It takes almost any text as input that looks like the name or code of a microorganism like "E. coli", "esco" and "esccol". Moreover, it can group all coagulase negative and positive *Staphylococci*, and can transform *Streptococci* into Lancefield groups. This package has a database of ~2500 different (potential) human pathogenic microorganisms.
* Use `as.rsi` to transform values to valid antimicrobial results. It produces just S, I or R based on your input and warns about invalid values. Even values like "<=0.002; S" (combined MIC/RSI) will result in "S".
* Use `as.mic` to cleanse your MIC values. It produces a so-called factor (in SPSS calls this *ordinal*) with valid MIC values as levels. A value like "<=0.002; S" (combined MIC/RSI) will result in "<=0.002".
* Use `as.atc` to get the ATC code of an antibiotic as defined by the WHO. This package contains a database with most LIS codes, official names, DDDs and even trade names of antibiotics. For example, the values "Furabid", "Furadantine", "nitro" will return the ATC code of Nitrofurantoine.
**Read all changes and new functions in [NEWS.md](NEWS.md).** 2. It **enhances existing data** and **adds new data** from data sets included in this package.
* Use `EUCAST_rules` to apply [EUCAST expert rules to isolates](http://www.eucast.org/expert_rules_and_intrinsic_resistance/).
* Use `MDRO` (abbreviation of Multi Drug Resistant Organisms) to check your isolates for exceptional resistance with country-specific guidelines with or EUCAST rules. Currently, national guidelines for Germany and the Netherlands are supported.
* Data set `microorganisms` contains the family, genus, species, subspecies, colloqual name and Gram stain of almost 2500 microorganisms. This enables e.g. resistance analysis of different antibiotics per Gram stain.
* Data set `antibiotics` contains the ATC code, LIS codes, official name, trivial name, trade name and DDD of both oral and parenteral administration.
* Use `first_isolate` to identify the first isolates of every patient [using guidelines from the CLSI](https://clsi.org/standards/products/microbiology/documents/m39/) (Clinical and Laboratory Standards Institute). * You can also identify first *weighted* isolates of every patient, an adjusted version of the CLSI guideline. This takes into account key antibiotics of every strain and compares them.
3. It **analyses the data** with convenient functions that use well-known methods.
* Calculate the resistance (and even co-resistance) of microbial isolates with the `portion_R`, `portion_IR`, `portion_I`, `portion_SI` and `portion_S` functions, that can also be used with the `dplyr` package (e.g. in conjunction with `summarise`)
* Plot AMR results with `geom_rsi`, a function made for the `ggplot2` package
* Predict antimicrobial resistance for the nextcoming years using logistic regression models with the `resistance_predict` function
* Conduct descriptive statistics to enhance base R: calculate kurtosis, skewness and create frequency tables
4. It **teaches the user** how to use all the above actions, by showing many examples in the help pages. The package contains an example data set called `septic_patients`. This data set, consisting of 2000 blood culture isolates from anonymised septic patients between 2001 and 2017 in the Northern Netherlands, is real and genuine data.
## How to get it? ## How to get it?
All versions of this package [are published on CRAN](http://cran.r-project.org/package=AMR), the official R network with a peer-reviewed submission process. All versions of this package [are published on CRAN](http://cran.r-project.org/package=AMR), the official R network with a peer-reviewed submission process.

Binary file not shown.

View File

@ -7,24 +7,24 @@
\code{\link{antibiotics}} \code{\link{antibiotics}}
} }
\usage{ \usage{
abname(abcode, from = c("guess", "atc", "molis", "umcg"), abname(abcode, from = c("guess", "atc", "certe", "umcg"),
to = "official", textbetween = " + ", tolower = FALSE) to = "official", textbetween = " + ", tolower = FALSE)
} }
\arguments{ \arguments{
\item{abcode}{a code or name, like \code{"AMOX"}, \code{"AMCL"} or \code{"J01CA04"}} \item{abcode}{a code or name, like \code{"AMOX"}, \code{"AMCL"} or \code{"J01CA04"}}
\item{from, to}{type to transform from and to. See \code{\link{antibiotics}} for its column names. WIth \code{from = "guess"} the from will be guessed from \code{"atc"}, \code{"molis"} and \code{"umcg"}. When using \code{to = "atc"}, the ATC code will be searched using \code{\link{guess_atc}}.} \item{from, to}{type to transform from and to. See \code{\link{antibiotics}} for its column names. WIth \code{from = "guess"} the from will be guessed from \code{"atc"}, \code{"certe"} and \code{"umcg"}. When using \code{to = "atc"}, the ATC code will be searched using \code{\link{as.atc}}.}
\item{textbetween}{text to put between multiple returned texts} \item{textbetween}{text to put between multiple returned texts}
\item{tolower}{return output as lower case with function \code{\link{tolower}}.} \item{tolower}{return output as lower case with function \code{\link{tolower}}.}
} }
\description{ \description{
Convert antibiotic codes (from a laboratory information system like MOLIS or GLIMS) to a (trivial) antibiotic name or ATC code, or vice versa. This uses the data from \code{\link{antibiotics}}. Convert antibiotic codes to a (trivial) antibiotic name or ATC code, or vice versa. This uses the data from \code{\link{antibiotics}}.
} }
\examples{ \examples{
abname("AMCL") abname("AMCL")
# "amoxicillin and enzyme inhibitor" # "Amoxicillin and beta-lactamase inhibitor"
# It is quite flexible at default (having `from = "guess"`) # It is quite flexible at default (having `from = "guess"`)
abname(c("amox", "J01CA04", "Trimox", "dispermox", "Amoxil")) abname(c("amox", "J01CA04", "Trimox", "dispermox", "Amoxil"))
@ -47,6 +47,10 @@ abname("AMCL", to = "atc")
# specific codes for University Medical Center Groningen (UMCG): # specific codes for University Medical Center Groningen (UMCG):
abname("J01CR02", from = "atc", to = "umcg") abname("J01CR02", from = "atc", to = "umcg")
# "AMCL" # "AMCL"
# specific codes for Certe:
abname("J01CR02", from = "atc", to = "certe")
# "amcl"
} }
\keyword{ab} \keyword{ab}
\keyword{antibiotics} \keyword{antibiotics}

View File

@ -7,7 +7,7 @@
\format{A data.frame with 420 observations and 18 variables: \format{A data.frame with 420 observations and 18 variables:
\describe{ \describe{
\item{\code{atc}}{ATC code, like \code{J01CR02}} \item{\code{atc}}{ATC code, like \code{J01CR02}}
\item{\code{molis}}{MOLIS code, like \code{amcl}} \item{\code{certe}}{Certe code, like \code{amcl}}
\item{\code{umcg}}{UMCG code, like \code{AMCL}} \item{\code{umcg}}{UMCG code, like \code{AMCL}}
\item{\code{abbr}}{Abbreviation as used by many countries, to be used for \code{\link{guess_atc}}} \item{\code{abbr}}{Abbreviation as used by many countries, to be used for \code{\link{guess_atc}}}
\item{\code{official}}{Official name by the WHO, like \code{"Amoxicillin and enzyme inhibitor"}} \item{\code{official}}{Official name by the WHO, like \code{"Amoxicillin and enzyme inhibitor"}}

28
man/guess_atc.Rd → man/as.atc.Rd Executable file → Normal file
View File

@ -1,16 +1,23 @@
% Generated by roxygen2: do not edit by hand % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/atc.R % Please edit documentation in R/atc.R
\name{guess_atc} \name{as.atc}
\alias{as.atc}
\alias{atc}
\alias{guess_atc} \alias{guess_atc}
\alias{is.atc}
\title{Find ATC code based on antibiotic property} \title{Find ATC code based on antibiotic property}
\usage{ \usage{
as.atc(x)
guess_atc(x) guess_atc(x)
is.atc(x)
} }
\arguments{ \arguments{
\item{x}{character vector to determine \code{ATC} code} \item{x}{character vector to determine \code{ATC} code}
} }
\value{ \value{
Character (vector). Character (vector) with class \code{"act"}. Unknown values will return \code{NA}.
} }
\description{ \description{
Use this function to determine the ATC code of one or more antibiotics. The dataset \code{\link{antibiotics}} will be searched for abbreviations, official names and trade names. Use this function to determine the ATC code of one or more antibiotics. The dataset \code{\link{antibiotics}} will be searched for abbreviations, official names and trade names.
@ -21,15 +28,16 @@ In the ATC classification system, the active substances are classified in a hier
} }
\examples{ \examples{
# These examples all return "J01FA01", the ATC code of Erythromycin: # These examples all return "J01FA01", the ATC code of Erythromycin:
guess_atc("J01FA01") as.atc("J01FA01")
guess_atc("Erythromycin") as.atc("Erythromycin")
guess_atc("eryt") as.atc("eryt")
guess_atc("ERYT") as.atc("ERYT")
guess_atc("ERY") as.atc("ERY")
guess_atc("Erythrocin") # Trade name as.atc("Erythrocin") # Trade name
guess_atc("Eryzole") # Trade name as.atc("Eryzole") # Trade name
guess_atc("Pediamycin") # Trade name as.atc("Pediamycin") # Trade name
} }
\seealso{ \seealso{
\code{\link{antibiotics}} for the dataframe that is being used to determine ATC's. \code{\link{antibiotics}} for the dataframe that is being used to determine ATC's.
} }
\keyword{atc}

View File

@ -1,5 +1,5 @@
% Generated by roxygen2: do not edit by hand % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/classes.R % Please edit documentation in R/mic.R
\name{as.mic} \name{as.mic}
\alias{as.mic} \alias{as.mic}
\alias{is.mic} \alias{is.mic}

View File

@ -1,5 +1,5 @@
% Generated by roxygen2: do not edit by hand % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/classes.R % Please edit documentation in R/rsi.R
\name{as.rsi} \name{as.rsi}
\alias{as.rsi} \alias{as.rsi}
\alias{is.rsi} \alias{is.rsi}

27
man/atc.property.Rd Normal file
View File

@ -0,0 +1,27 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/atc.R
\name{atc.property}
\alias{atc.property}
\alias{atc.official}
\alias{atc.official_nl}
\alias{atc.trivial_nl}
\alias{atc.certe}
\alias{atc.umcg}
\title{Get antibiotic property based on ATC}
\usage{
atc.official(atc)
atc.official_nl(atc)
atc.trivial_nl(atc)
atc.certe(atc)
atc.umcg(atc)
}
\arguments{
\item{atc}{a valid ATC code, created with \code{\link{as.atc}}}
}
\description{
Use these functions to return a specific property of an antibiotic from the \code{\link{antibiotics}} data set, based on their ATC code.
}

42
man/bactid.property.Rd Normal file
View File

@ -0,0 +1,42 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/bactid.R
\name{bactid.property}
\alias{bactid.property}
\alias{bactid.family}
\alias{bactid.genus}
\alias{bactid.species}
\alias{bactid.subspecies}
\alias{bactid.fullname}
\alias{bactid.type}
\alias{bactid.gramstain}
\alias{bactid.aerobic}
\alias{bactid.type_nl}
\alias{bactid.gramstain_nl}
\title{Get microbial property based on `bactid`}
\usage{
bactid.family(bactid)
bactid.genus(bactid)
bactid.species(bactid)
bactid.subspecies(bactid)
bactid.fullname(bactid)
bactid.type(bactid)
bactid.gramstain(bactid)
bactid.aerobic(bactid)
bactid.type_nl(bactid)
bactid.gramstain_nl(bactid)
}
\arguments{
\item{bactid}{a valid bactid code, created with \code{\link{as.bactid}}}
}
\description{
Use these functions to return a specific property of a microorganism from the \code{\link{microorganisms}} data set, based on their \code{bactid}. Get such an ID with \code{\link{as.bactid}}.
}

View File

@ -1,19 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/eucast.R
\name{mo_property}
\alias{mo_property}
\title{Poperties of a microorganism}
\usage{
mo_property(bactid, property = "fullname")
}
\arguments{
\item{bactid}{ID of a microorganisme, like \code{"STAAUR} and \code{"ESCCOL}}
\item{property}{One of the values \code{bactid}, \code{bactsys}, \code{family}, \code{genus}, \code{species}, \code{subspecies}, \code{fullname}, \code{type}, \code{gramstain}, \code{aerobic}}
}
\description{
Poperties of a microorganism
}
\seealso{
\code{\link{microorganisms}}
}

View File

@ -1,5 +1,5 @@
% Generated by roxygen2: do not edit by hand % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/rsi.R % Please edit documentation in R/portion.R
\name{rsi} \name{rsi}
\alias{rsi} \alias{rsi}
\title{Calculate resistance of isolates} \title{Calculate resistance of isolates}

View File

@ -5,7 +5,7 @@ test_that("abname works", {
expect_equal(abname(c("AMOX", "GENT")), c("Amoxicillin", "Gentamicin")) expect_equal(abname(c("AMOX", "GENT")), c("Amoxicillin", "Gentamicin"))
expect_equal(abname(c("AMOX+GENT")), "Amoxicillin + gentamicin") expect_equal(abname(c("AMOX+GENT")), "Amoxicillin + gentamicin")
expect_equal(abname("AMOX", from = 'umcg'), "Amoxicillin") expect_equal(abname("AMOX", from = 'umcg'), "Amoxicillin")
expect_equal(abname("amox", from = 'molis', tolower = TRUE), "amoxicillin") expect_equal(abname("amox", from = 'certe', tolower = TRUE), "amoxicillin")
expect_equal(abname("J01CA04", from = 'atc'), "Amoxicillin") expect_equal(abname("J01CA04", from = 'atc'), "Amoxicillin")
expect_equal(abname(c("amox", "J01CA04", "Trimox", "dispermox", "Amoxil")), expect_equal(abname(c("amox", "J01CA04", "Trimox", "dispermox", "Amoxil")),
rep("Amoxicillin", 5)) rep("Amoxicillin", 5))

View File

@ -22,14 +22,25 @@ test_that("atc_property works", {
}) })
test_that("guess_atc works", { test_that("guess_atc works", {
expect_equal(guess_atc(c("J01FA01", expect_equal(as.character(guess_atc(c("J01FA01",
"Erythromycin", "Erythromycin",
"eryt", "eryt",
"ERYT", "ERYT",
"ERY", "ERY",
"Erythrocin", "Erythrocin",
"Eryzole", "Eryzole",
"Pediamycin")), "Pediamycin"))),
rep("J01FA01", 8)) rep("J01FA01", 8))
expect_identical(class(as.atc("amox")), "atc")
})
test_that("atc.property works", {
expect_equal(atc.certe("J01CA04"), "amox")
expect_equal(atc.umcg("J01CA04"), "AMOX")
expect_equal(atc.official("J01CA04"), "Amoxicillin")
expect_equal(atc.official_nl("J01CA04"), "Amoxicilline")
expect_equal(atc.trivial_nl("J01CA04"), "Amoxicilline")
}) })

View File

@ -108,3 +108,16 @@ test_that("as.bactid works", {
NA_character_) NA_character_)
}) })
test_that("bactid.property works", {
expect_equal(bactid.family("E. coli"), "Enterobacteriaceae")
expect_equal(bactid.genus("E. coli"), "Escherichia")
expect_equal(bactid.species("E. coli"), "coli")
expect_equal(bactid.subspecies("E. coli"), NA_character_)
expect_equal(bactid.fullname("E. coli"), "Escherichia coli")
expect_equal(bactid.type("E. coli"), "Bacteria")
expect_equal(bactid.gramstain("E. coli"), "Negative rods")
expect_equal(bactid.aerobic("E. coli"), TRUE)
expect_equal(bactid.type_nl("E. coli"), "Bacterie")
expect_equal(bactid.gramstain_nl("E. coli"), "Negatieve staven")
})

View File

@ -32,8 +32,3 @@ test_that("EUCAST rules work", {
stringsAsFactors = FALSE) stringsAsFactors = FALSE)
expect_equal(suppressWarnings(EUCAST_rules(a, info = FALSE)), b) expect_equal(suppressWarnings(EUCAST_rules(a, info = FALSE)), b)
}) })
test_that("MO properties work", {
expect_equal(mo_property("ESCCOL"), "Escherichia coli")
expect_equal(mo_property("STAAUR"), "Staphylococcus aureus")
})

View File

@ -1,25 +1,4 @@
context("classes.R") context("mic.R")
test_that("rsi works", {
expect_true(as.rsi("S") < as.rsi("I"))
expect_true(as.rsi("I") < as.rsi("R"))
expect_true(as.rsi("R") > as.rsi("S"))
expect_true(is.rsi(as.rsi("S")))
# print plots, should not raise errors
barplot(as.rsi(c("S", "I", "R")))
plot(as.rsi(c("S", "I", "R")))
print(as.rsi(c("S", "I", "R")))
expect_equal(suppressWarnings(as.logical(as.rsi("INVALID VALUE"))), NA)
expect_equal(summary(as.rsi(c("S", "R"))), c("Mode" = 'rsi',
"<NA>" = "0",
"Sum S" = "1",
"Sum IR" = "1",
"-Sum R" = "1",
"-Sum I" = "0"))
})
test_that("mic works", { test_that("mic works", {
expect_true(as.mic(8) == as.mic("8")) expect_true(as.mic(8) == as.mic("8"))

22
tests/testthat/test-rsi.R Normal file
View File

@ -0,0 +1,22 @@
context("rsi.R")
test_that("rsi works", {
expect_true(as.rsi("S") < as.rsi("I"))
expect_true(as.rsi("I") < as.rsi("R"))
expect_true(as.rsi("R") > as.rsi("S"))
expect_true(is.rsi(as.rsi("S")))
# print plots, should not raise errors
barplot(as.rsi(c("S", "I", "R")))
plot(as.rsi(c("S", "I", "R")))
print(as.rsi(c("S", "I", "R")))
expect_equal(suppressWarnings(as.logical(as.rsi("INVALID VALUE"))), NA)
expect_equal(summary(as.rsi(c("S", "R"))), c("Mode" = 'rsi',
"<NA>" = "0",
"Sum S" = "1",
"Sum IR" = "1",
"-Sum R" = "1",
"-Sum I" = "0"))
})

58
vignettes/AMR.Rmd Executable file
View File

@ -0,0 +1,58 @@
---
title: "Introduction to the AMR package"
author: "Matthijs S. Berends"
output:
rmarkdown::html_vignette:
toc: true
vignette: >
%\VignetteIndexEntry{Creating Frequency Tables}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include = FALSE, results = 'markup'}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#"
)
```
This R package was intended to make microbial epidemiology easier. Most functions contain extensive help pages to get started.
This `AMR` package basically does four important things:
1. It **cleanses existing data**, by transforming it to reproducible and profound *classes*, making the most efficient use of R. These function all use artificial intelligence to get expected results:
* Use `as.bactid` to get an ID of a microorganism. It takes almost any text as input that looks like the name or code of a microorganism like "E. coli", "esco" and "esccol". Moreover, it can group all coagulase negative and positive *Staphylococci*, and can transform *Streptococci* into Lancefield groups. This package has a database of ~2500 different (potential) human pathogenic microorganisms.
* Use `as.rsi` to transform values to valid antimicrobial results. It produces just S, I or R based on your input and warns about invalid values. Even values like "<=0.002; S" (combined MIC/RSI) will result in "S".
* Use `as.mic` to cleanse your MIC values. It produces a so-called factor (in SPSS calls this *ordinal*) with valid MIC values as levels. A value like "<=0.002; S" (combined MIC/RSI) will result in "<=0.002".
* Use `as.atc` to get the ATC code of an antibiotic as defined by the WHO. This package contains a database with most LIS codes, official names, DDDs and even trade names of antibiotics. For example, the values "Furabid", "Furadantine", "nitro" will return the ATC code of Nitrofurantoine.
2. It **enhances existing data** and **adds new data** from data sets included in this package.
* Use `EUCAST_rules` to apply [EUCAST expert rules to isolates](http://www.eucast.org/expert_rules_and_intrinsic_resistance/).
* Use `MDRO` (abbreviation of Multi Drug Resistant Organisms) to check your isolates for exceptional resistance with country-specific guidelines with or EUCAST rules. Currently, national guidelines for Germany and the Netherlands are supported.
* Data set `microorganisms` contains the family, genus, species, subspecies, colloqual name and Gram stain of almost 2500 microorganisms. This enables e.g. resistance analysis of different antibiotics per Gram stain.
* Data set `antibiotics` contains the ATC code, LIS codes, official name, trivial name, trade name and DDD of both oral and parenteral administration.
* Use `first_isolate` to identify the first isolates of every patient [using guidelines from the CLSI](https://clsi.org/standards/products/microbiology/documents/m39/) (Clinical and Laboratory Standards Institute). * You can also identify first *weighted* isolates of every patient, an adjusted version of the CLSI guideline. This takes into account key antibiotics of every strain and compares them.
3. It **analyses the data** with convenient functions that use well-known methods.
* Calculate the resistance (and even co-resistance) of microbial isolates with the `portion_R`, `portion_IR`, `portion_I`, `portion_SI` and `portion_S` functions, that can also be used with the `dplyr` package (e.g. in conjunction with `summarise`)
* Plot AMR results with `geom_rsi`, a function made for the `ggplot2` package
* Predict antimicrobial resistance for the nextcoming years using logistic regression models with the `resistance_predict` function
* Conduct descriptive statistics to enhance base R: calculate kurtosis, skewness and create frequency tables
4. It **teaches the user** how to use all the above actions, by showing many examples in the help pages. The package contains an example data set called `septic_patients`. This data set, consisting of 2000 blood culture isolates from anonymised septic patients between 2001 and 2017 in the Northern Netherlands, is real and genuine data.
----
```{r, echo = FALSE}
# this will print "2018" in 2018, and "2018-yyyy" after 2018.
yrs <- c(2018:format(Sys.Date(), "%Y"))
yrs <- c(min(yrs), max(yrs))
yrs <- paste(unique(yrs), collapse = "-")
```
AMR, (c) `r yrs`, `r packageDescription("AMR")$URL`
Licensed under the [GNU General Public License v2.0](https://github.com/msberends/AMR/blob/master/LICENSE).