rsi family for resistance analysis

This commit is contained in:
dr. M.S. (Matthijs) Berends 2018-08-03 14:49:29 +02:00
parent 227121af3d
commit ae2433a020
15 changed files with 421 additions and 196 deletions

View File

@ -1,6 +1,6 @@
Package: AMR
Version: 0.2.0.9020
Date: 2018-08-02
Version: 0.2.0.9021
Date: 2018-08-03
Title: Antimicrobial Resistance Analysis
Authors@R: c(
person(

View File

@ -31,12 +31,8 @@ export("%like%")
export(BRMO)
export(EUCAST_exceptional_phenotypes)
export(EUCAST_rules)
export(IR)
export(MDRO)
export(MRGN)
export(R)
export(S)
export(SI)
export(abname)
export(anti_join_microorganisms)
export(as.bactid)
@ -55,6 +51,7 @@ export(g.test)
export(guess_atc)
export(guess_bactid)
export(inner_join_microorganisms)
export(intermediate)
export(interpretive_reading)
export(is.bactid)
export(is.mic)
@ -72,6 +69,12 @@ export(resistance)
export(resistance_predict)
export(right_join_microorganisms)
export(rsi)
export(rsi_I)
export(rsi_IR)
export(rsi_R)
export(rsi_S)
export(rsi_SI)
export(rsi_n)
export(rsi_predict)
export(semi_join_microorganisms)
export(skewness)

View File

@ -2,7 +2,7 @@
**Published on CRAN: (unpublished)**
#### New
* **BREAKING**: `rsi_df` was removed in favour of new functions `R`, `IR`, `SI` and `S` to selectively calculate resistance or susceptibility. These functions use **hybrid evaluation**, which means that calculations are not done in R directly but rather in C++ using the `Rcpp` package, making them 20 to 30 times faster. The function `rsi` still works, but is deprecated.
* **BREAKING**: `rsi_df` was removed in favour of new functions `rsi_R`, `rsi_IR`, `rsi_I`, `rsi_SI` and `rsi_S` to selectively calculate resistance or susceptibility. These functions use **hybrid evaluation**, which means that calculations are not done in R directly but rather in C++ using the `Rcpp` package, making them 20 to 30 times faster. The function `rsi` still works, but is deprecated. The function `n_rsi` is accompanied by `rsi_n`.
* **BREAKING**: the methodology for determining first weighted isolates was changed. The antibiotics that are compared between isolates (call *key antibiotics*) to include more first isolates (afterwards called first *weighted* isolates) are now as follows:
* Universal: amoxicillin, amoxicillin/clavlanic acid, cefuroxime, piperacillin/tazobactam, ciprofloxacin, trimethoprim/sulfamethoxazole
* Gram-positive: vancomycin, teicoplanin, tetracycline, erythromycin, oxacillin, rifampicin

View File

@ -5,6 +5,10 @@ rsi_calc_S <- function(x, include_I) {
.Call(`_AMR_rsi_calc_S`, x, include_I)
}
rsi_calc_I <- function(x) {
.Call(`_AMR_rsi_calc_I`, x)
}
rsi_calc_R <- function(x, include_I) {
.Call(`_AMR_rsi_calc_R`, x, include_I)
}

View File

@ -23,6 +23,7 @@
#' @param Becker a logical to indicate whether \emph{Staphylococci} should be categorised into Coagulase Negative \emph{Staphylococci} ("CoNS") and Coagulase Positive \emph{Staphylococci} ("CoPS") instead of their own species, according to Karsten Becker \emph{et al.} [1]. This excludes \emph{Staphylococcus aureus} at default, use \code{Becker = "all"} to also categorise \emph{S. aureus} as "CoPS".
#' @param Lancefield a logical to indicate whether beta-haemolytic \emph{Streptococci} should be categorised into Lancefield groups instead of their own species, according to Rebecca C. Lancefield [2]. These \emph{Streptococci} will be categorised in their first group, i.e. \emph{Streptococcus dysgalactiae} will be group C, although officially it was also categorised into groups G and L. Groups D and E will be ignored, since they are \emph{Enterococci}.
#' @rdname as.bactid
#' @keywords bactid Becker becker Lancefield lancefield guess
#' @details \code{guess_bactid} is an alias of \code{as.bactid}.
#'
#' Some exceptions have been built in to get more logical results, based on prevalence of human pathogens. These are:

View File

@ -18,20 +18,17 @@
#' Calculate resistance of isolates
#'
#' These functions can be used to calculate the (co-)resistance of microbial isolates (i.e. percentage S, SI, IR or R). All functions can be used in \code{dplyr}s \code{\link[dplyr]{summarise}} and support grouped variables, see \emph{Examples}. \cr\cr
#' \code{R} and \code{IR} can be used to calculate resistance, \code{S} and \code{SI} can be used to calculate susceptibility.\cr
#' \code{n_rsi} counts all cases where antimicrobial interpretations are available.
#' These functions can be used to calculate the (co-)resistance of microbial isolates (i.e. percentage S, SI, I, IR or R). All functions can be used in \code{dplyr}s \code{\link[dplyr]{summarise}} and support grouped variables, see \emph{Examples}. \cr\cr
#' \code{rsi_R} and \code{rsi_IR} can be used to calculate resistance, \code{rsi_S} and \code{rsi_SI} can be used to calculate susceptibility.\cr
#' \code{rsi_n} counts all cases where antimicrobial interpretations are available.
#' @param ab1 vector of antibiotic interpretations, they will be transformed internally with \code{\link{as.rsi}}
#' @param ab2 like \code{ab}, a vector of antibiotic interpretations. Use this to calculate (the lack of) co-resistance: the probability where one of two drugs have a susceptible result. See Examples.
#' @param include_I logical to indicate whether antimicrobial interpretations of "I" should be included
#' @param minimum minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA}. The default number of \code{30} isolates is advised by the CLSI as best practice, see Source.
#' @param as_percent logical to indicate whether the output must be returned as percent (text), will else be a double
#' @param interpretation antimicrobial interpretation
#' @param info \emph{DEPRECATED} calculate the amount of available isolates and print it, like \code{n = 423}
#' @param warning \emph{DEPRECATED} show a warning when the available amount of isolates is below \code{minimum}
#' @details \strong{Remember that you should filter your table to let it contain only first isolates!} Use \code{\link{first_isolate}} to determine them in your data set.
#'
#' The functions \code{resistance} and \code{susceptibility} are wrappers around \code{IR} and \code{S}, respectively. All functions except \code{rsi} use hybrid evaluation (i.e. using C++), which makes these functions 20-30 times faster than the old \code{rsi} function. This latter function is still available for backwards compatibility but is deprecated.
#' The functions \code{resistance} and \code{susceptibility} are wrappers around \code{rsi_IR} and \code{rsi_S}, respectively. All functions use hybrid evaluation (i.e. using C++), which makes these functions 20-30 times faster than the old \code{\link{rsi}} function. This latter function is still available for backwards compatibility but is deprecated.
#' \if{html}{
#' \cr\cr
#' To calculate the probability (\emph{p}) of susceptibility of one antibiotic, we use this formula:
@ -47,48 +44,57 @@
#' @source \strong{M39 Analysis and Presentation of Cumulative Antimicrobial Susceptibility Test Data, 4th Edition}, 2014, \emph{Clinical and Laboratory Standards Institute (CLSI)}. \url{https://clsi.org/standards/products/microbiology/documents/m39/}.
#' @keywords resistance susceptibility rsi_df rsi antibiotics isolate isolates
#' @return Double or, when \code{as_percent = TRUE}, a character.
#' @rdname resistance
#' @rdname rsi_IR
#' @name rsi_IR
#' @export
#' @examples
#' # Calculate resistance
#' R(septic_patients$amox)
#' IR(septic_patients$amox)
#' rsi_R(septic_patients$amox)
#' rsi_IR(septic_patients$amox)
#'
#' # Or susceptibility
#' S(septic_patients$amox)
#' SI(septic_patients$amox)
#' rsi_S(septic_patients$amox)
#' rsi_SI(septic_patients$amox)
#'
#' # Since n_rsi counts available isolates (and is used as denominator),
#' # you can calculate back to e.g. count resistant isolates:
#' IR(septic_patients$amox) * n_rsi(septic_patients$amox)
#' rsi_IR(septic_patients$amox) * n_rsi(septic_patients$amox)
#'
#' library(dplyr)
#' septic_patients %>%
#' group_by(hospital_id) %>%
#' summarise(p = S(cipr),
#' n = n_rsi(cipr)) # n_rsi works like n_distinct in dplyr
#'
#' # Calculate co-resistance between amoxicillin/clav acid and gentamicin,
#' # so we can see that combination therapy does a lot more than mono therapy:
#' S(septic_patients$amcl) # p = 67.3%
#' n_rsi(septic_patients$amcl) # n = 1570
#'
#' S(septic_patients$gent) # p = 74.0%
#' n_rsi(septic_patients$gent) # n = 1842
#'
#' with(septic_patients,
#' S(amcl, gent)) # p = 92.1%
#' with(septic_patients,
#' n_rsi(amcl, gent)) # n = 1504
#' summarise(p = rsi_S(cipr),
#' n = rsi_n(cipr)) # n_rsi works like n_distinct in dplyr
#'
#' septic_patients %>%
#' group_by(hospital_id) %>%
#' summarise(cipro_p = S(cipr, as_percent = TRUE),
#' cipro_n = n_rsi(cipr),
#' genta_p = S(gent, as_percent = TRUE),
#' genta_n = n_rsi(gent),
#' combination_p = S(cipr, gent, as_percent = TRUE),
#' combination_n = n_rsi(cipr, gent))
#' summarise(R = rsi_R(cipr, as_percent = TRUE),
#' I = rsi_I(cipr, as_percent = TRUE),
#' S = rsi_S(cipr, as_percent = TRUE),
#' n = rsi_n(cipr), # also: n_rsi, works like n_distinct in dplyr
#' total = n()) # this is the length, NOT the amount of tested isolates
#'
#' # Calculate co-resistance between amoxicillin/clav acid and gentamicin,
#' # so we can see that combination therapy does a lot more than mono therapy:
#' rsi_S(septic_patients$amcl) # S = 67.3%
#' rsi_n(septic_patients$amcl) # n = 1570
#'
#' rsi_S(septic_patients$gent) # S = 74.0%
#' rsi_n(septic_patients$gent) # n = 1842
#'
#' with(septic_patients,
#' rsi_S(amcl, gent)) # S = 92.1%
#' with(septic_patients, # n = 1504
#' rsi_n(amcl, gent))
#'
#' septic_patients %>%
#' group_by(hospital_id) %>%
#' summarise(cipro_p = rsi_S(cipr, as_percent = TRUE),
#' cipro_n = rsi_n(cipr),
#' genta_p = rsi_S(gent, as_percent = TRUE),
#' genta_n = rsi_n(gent),
#' combination_p = rsi_S(cipr, gent, as_percent = TRUE),
#' combination_n = rsi_n(cipr, gent))
#'
#' \dontrun{
#'
@ -96,31 +102,45 @@
#' my_table %>%
#' filter(first_isolate == TRUE,
#' genus == "Helicobacter") %>%
#' summarise(p = S(amox, metr), # amoxicillin with metronidazole
#' n = n_rsi(amox, metr))
#' summarise(p = rsi_S(amox, metr), # amoxicillin with metronidazole
#' n = rsi_n(amox, metr))
#' }
#' @rdname resistance
#' @name resistance
#' @export
#' @rdname resistance
#' @export
S <- function(ab1,
ab2 = NULL,
minimum = 30,
as_percent = FALSE) {
susceptibility(ab1 = ab1,
ab2 = ab2,
include_I = FALSE,
minimum = minimum,
as_percent = as_percent)
rsi_R <- function(ab1,
minimum = 30,
as_percent = FALSE) {
resistance(ab1 = ab1,
include_I = FALSE,
minimum = minimum,
as_percent = as_percent)
}
#' @rdname resistance
#' @rdname rsi_IR
#' @export
SI <- function(ab1,
ab2 = NULL,
minimum = 30,
as_percent = FALSE) {
rsi_IR <- function(ab1,
minimum = 30,
as_percent = FALSE) {
resistance(ab1 = ab1,
include_I = TRUE,
minimum = minimum,
as_percent = as_percent)
}
#' @rdname rsi_IR
#' @export
rsi_I <- function(ab1,
minimum = 30,
as_percent = FALSE) {
intermediate(ab1 = ab1,
minimum = minimum,
as_percent = as_percent)
}
#' @rdname rsi_IR
#' @export
rsi_SI <- function(ab1,
ab2 = NULL,
minimum = 30,
as_percent = FALSE) {
susceptibility(ab1 = ab1,
ab2 = ab2,
include_I = TRUE,
@ -128,51 +148,20 @@ SI <- function(ab1,
as_percent = as_percent)
}
#' @rdname resistance
#' @rdname rsi_IR
#' @export
IR <- function(ab1,
minimum = 30,
as_percent = FALSE) {
resistance(ab1 = ab1,
include_I = TRUE,
minimum = minimum,
as_percent = as_percent)
rsi_S <- function(ab1,
ab2 = NULL,
minimum = 30,
as_percent = FALSE) {
susceptibility(ab1 = ab1,
ab2 = ab2,
include_I = FALSE,
minimum = minimum,
as_percent = as_percent)
}
#' @rdname resistance
#' @export
R <- function(ab1,
minimum = 30,
as_percent = FALSE) {
resistance(ab1 = ab1,
include_I = FALSE,
minimum = minimum,
as_percent = as_percent)
}
#' @rdname resistance
#' @export
n_rsi <- function(ab1, ab2 = NULL) {
if (NCOL(ab1) > 1) {
stop('`ab` must be a vector of antimicrobial interpretations', call. = FALSE)
}
if (!is.rsi(ab1)) {
ab1 <- as.rsi(ab1)
}
if (!is.null(ab2)) {
if (NCOL(ab2) > 1) {
stop('`ab2` must be a vector of antimicrobial interpretations', call. = FALSE)
}
if (!is.rsi(ab2)) {
ab2 <- as.rsi(ab2)
}
sum(!is.na(ab1) & !is.na(ab2))
} else {
sum(!is.na(ab1))
}
}
#' @rdname resistance
#' @rdname rsi_IR
#' @export
resistance <- function(ab1,
include_I = TRUE,
@ -214,7 +203,45 @@ resistance <- function(ab1,
}
}
#' @rdname resistance
#' @rdname rsi_IR
#' @export
intermediate <- function(ab1,
minimum = 30,
as_percent = FALSE) {
if (NCOL(ab1) > 1) {
stop('`ab1` must be a vector of antimicrobial interpretations', call. = FALSE)
}
if (!is.numeric(minimum)) {
stop('`minimum` must be numeric', call. = FALSE)
}
if (!is.logical(as_percent)) {
stop('`as_percent` must be logical', call. = FALSE)
}
# ab_name <- deparse(substitute(ab))
if (!is.rsi(ab1)) {
x <- as.rsi(ab1)
warning("Increase speed by transforming to class `rsi` on beforehand: df %>% mutate_at(vars(col10:col20), as.rsi)")
} else {
x <- ab1
}
total <- length(x) - sum(is.na(x)) # faster than C++
if (total < minimum) {
# warning("Too few isolates available for ", ab_name, ": ", total, " < ", minimum, "; returning NA.", call. = FALSE)
return(NA)
}
found <- .Call(`_AMR_rsi_calc_I`, x)
if (as_percent == TRUE) {
percent(found / total, force_zero = TRUE)
} else {
found / total
}
}
#' @rdname rsi_IR
#' @export
susceptibility <- function(ab1,
ab2 = NULL,
@ -275,7 +302,37 @@ susceptibility <- function(ab1,
}
}
#' @rdname resistance
#' @rdname rsi_IR
#' @export
rsi_n <- function(ab1, ab2 = NULL) {
if (NCOL(ab1) > 1) {
stop('`ab` must be a vector of antimicrobial interpretations', call. = FALSE)
}
if (!is.rsi(ab1)) {
ab1 <- as.rsi(ab1)
}
if (!is.null(ab2)) {
if (NCOL(ab2) > 1) {
stop('`ab2` must be a vector of antimicrobial interpretations', call. = FALSE)
}
if (!is.rsi(ab2)) {
ab2 <- as.rsi(ab2)
}
sum(!is.na(ab1) & !is.na(ab2))
} else {
sum(!is.na(ab1))
}
}
#' @rdname rsi_IR
#' @export
n_rsi <- rsi_n
#' @inherit resistance
#' @description This function is deprecated. Use \code{\link{rsi_IR}} instead.
#' @param info calculate the amount of available isolates and print it, like \code{n = 423}
#' @param warning show a warning when the available amount of isolates is below \code{minimum}
#' @param interpretation antimicrobial interpretation
#' @export
rsi <- function(ab1,
ab2 = NA,

View File

@ -28,7 +28,7 @@ Erwin E.A. Hassing<sup>2</sup>,
This R package contains functions to make **microbiological, epidemiological data analysis easier**. It allows the use of some new classes to work with MIC values and antimicrobial interpretations (i.e. values S, I and R).
With `AMR` you can:
* Calculate the resistance (and even co-resistance) of microbial isolates with the `R`, `IR`, `SI` and `S` functions, that can also be used with the `dplyr` package (e.g. in conjunction with `summarise`)
* Calculate the resistance (and even co-resistance) of microbial isolates with the `rsi_R`, `rsi_IR`, `rsi_I`, `rsi_SI` and `rsi_S` functions, that can also be used with the `dplyr` package (e.g. in conjunction with `summarise`)
* Predict antimicrobial resistance for the nextcoming years 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
@ -121,17 +121,17 @@ after
# 5 PSEAER R R - - R
```
Bacteria ID's can be retrieved with the `as.bactid` function. It uses any type of info about a microorganism as input. For example, all these will return value `STAAUR`, the ID of *S. aureus*:
Bacteria ID's can be retrieved with the `guess_bactid` function. It uses any type of info about a microorganism as input. For example, all these will return value `STAAUR`, the ID of *S. aureus*:
```r
as.bactid("stau")
as.bactid("STAU")
as.bactid("staaur")
as.bactid("S. aureus")
as.bactid("S aureus")
as.bactid("Staphylococcus aureus")
as.bactid("MRSA") # Methicillin Resistant S. aureus
as.bactid("VISA") # Vancomycin Intermediate S. aureus
as.bactid("VRSA") # Vancomycin Resistant S. aureus
guess_bactid("stau")
guess_bactid("STAU")
guess_bactid("staaur")
guess_bactid("S. aureus")
guess_bactid("S aureus")
guess_bactid("Staphylococcus aureus")
guess_bactid("MRSA") # Methicillin Resistant S. aureus
guess_bactid("VISA") # Vancomycin Intermediate S. aureus
guess_bactid("VRSA") # Vancomycin Resistant S. aureus
```
### New classes

View File

@ -84,3 +84,9 @@ df <- df \%>\%
\seealso{
\code{\link{microorganisms}} for the dataframe that is being used to determine ID's.
}
\keyword{Becker}
\keyword{Lancefield}
\keyword{bactid}
\keyword{becker}
\keyword{guess}
\keyword{lancefield}

View File

@ -4,7 +4,7 @@
\name{microorganisms}
\alias{microorganisms}
\title{Dataset with ~2500 microorganisms}
\format{A data.frame with 2456 observations and 12 variables:
\format{A data.frame with 2464 observations and 12 variables:
\describe{
\item{\code{bactid}}{ID of microorganism}
\item{\code{bactsys}}{Bactsyscode of microorganism}
@ -23,7 +23,7 @@
microorganisms
}
\description{
A dataset containing 2456 microorganisms. MO codes of the UMCG can be looked up using \code{\link{microorganisms.umcg}}.
A dataset containing 2464 microorganisms. MO codes of the UMCG can be looked up using \code{\link{microorganisms.umcg}}.
}
\seealso{
\code{\link{guess_bactid}} \code{\link{antibiotics}} \code{\link{microorganisms.umcg}}

View File

@ -1,5 +1,5 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/resistance.R
% Please edit documentation in R/rsi_IR.R
\name{resistance_predict}
\alias{resistance_predict}
\alias{rsi_predict}

106
man/rsi.Rd Normal file
View File

@ -0,0 +1,106 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/rsi_IR.R
\name{rsi}
\alias{rsi}
\title{Calculate resistance of isolates}
\usage{
rsi(ab1, ab2 = NA, interpretation = "IR", minimum = 30,
as_percent = FALSE, info = FALSE, warning = TRUE)
}
\arguments{
\item{ab1}{vector of antibiotic interpretations, they will be transformed internally with \code{\link{as.rsi}}}
\item{ab2}{like \code{ab}, a vector of antibiotic interpretations. Use this to calculate (the lack of) co-resistance: the probability where one of two drugs have a susceptible result. See Examples.}
\item{interpretation}{antimicrobial interpretation}
\item{minimum}{minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA}. The default number of \code{30} isolates is advised by the CLSI as best practice, see Source.}
\item{as_percent}{logical to indicate whether the output must be returned as percent (text), will else be a double}
\item{info}{calculate the amount of available isolates and print it, like \code{n = 423}}
\item{warning}{show a warning when the available amount of isolates is below \code{minimum}}
}
\value{
Double or, when \code{as_percent = TRUE}, a character.
}
\description{
This function is deprecated. Use \code{\link{rsi_IR}} instead.
}
\details{
\strong{Remember that you should filter your table to let it contain only first isolates!} Use \code{\link{first_isolate}} to determine them in your data set.
The functions \code{resistance} and \code{susceptibility} are wrappers around \code{rsi_IR} and \code{rsi_S}, respectively. All functions use hybrid evaluation (i.e. using C++), which makes these functions 20-30 times faster than the old \code{\link{rsi}} function. This latter function is still available for backwards compatibility but is deprecated.
\if{html}{
\cr\cr
To calculate the probability (\emph{p}) of susceptibility of one antibiotic, we use this formula:
\out{<div style="text-align: center">}\figure{mono_therapy.png}\out{</div>}
To calculate the probability (\emph{p}) of susceptibility of more antibiotics (i.e. combination therapy), we need to check whether one of them has a susceptible result (as numerator) and count all cases where all antibiotics were tested (as denominator). \cr
\cr
For two antibiotics:
\out{<div style="text-align: center">}\figure{combi_therapy_2.png}\out{</div>}
\cr
Theoretically for three antibiotics:
\out{<div style="text-align: center">}\figure{combi_therapy_3.png}\out{</div>}
}
}
\examples{
# Calculate resistance
rsi_R(septic_patients$amox)
rsi_IR(septic_patients$amox)
# Or susceptibility
rsi_S(septic_patients$amox)
rsi_SI(septic_patients$amox)
# Since n_rsi counts available isolates (and is used as denominator),
# you can calculate back to e.g. count resistant isolates:
rsi_IR(septic_patients$amox) * n_rsi(septic_patients$amox)
library(dplyr)
septic_patients \%>\%
group_by(hospital_id) \%>\%
summarise(p = rsi_S(cipr),
n = rsi_n(cipr)) # n_rsi works like n_distinct in dplyr
septic_patients \%>\%
group_by(hospital_id) \%>\%
summarise(R = rsi_R(cipr, as_percent = TRUE),
I = rsi_I(cipr, as_percent = TRUE),
S = rsi_S(cipr, as_percent = TRUE),
n = rsi_n(cipr), # also: n_rsi, works like n_distinct in dplyr
total = n()) # this is the length, NOT the amount of tested isolates
# Calculate co-resistance between amoxicillin/clav acid and gentamicin,
# so we can see that combination therapy does a lot more than mono therapy:
rsi_S(septic_patients$amcl) # S = 67.3\%
rsi_n(septic_patients$amcl) # n = 1570
rsi_S(septic_patients$gent) # S = 74.0\%
rsi_n(septic_patients$gent) # n = 1842
with(septic_patients,
rsi_S(amcl, gent)) # S = 92.1\%
with(septic_patients, # n = 1504
rsi_n(amcl, gent))
septic_patients \%>\%
group_by(hospital_id) \%>\%
summarise(cipro_p = rsi_S(cipr, as_percent = TRUE),
cipro_n = rsi_n(cipr),
genta_p = rsi_S(gent, as_percent = TRUE),
genta_n = rsi_n(gent),
combination_p = rsi_S(cipr, gent, as_percent = TRUE),
combination_n = rsi_n(cipr, gent))
\dontrun{
# calculate current empiric combination therapy of Helicobacter gastritis:
my_table \%>\%
filter(first_isolate == TRUE,
genus == "Helicobacter") \%>\%
summarise(p = rsi_S(amox, metr), # amoxicillin with metronidazole
n = rsi_n(amox, metr))
}
}

View File

@ -1,66 +1,65 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/resistance.R
\name{resistance}
% Please edit documentation in R/rsi_IR.R
\name{rsi_IR}
\alias{rsi_IR}
\alias{rsi_R}
\alias{rsi_I}
\alias{rsi_SI}
\alias{rsi_S}
\alias{resistance}
\alias{S}
\alias{SI}
\alias{IR}
\alias{R}
\alias{n_rsi}
\alias{intermediate}
\alias{susceptibility}
\alias{rsi}
\alias{rsi_n}
\alias{n_rsi}
\title{Calculate resistance of isolates}
\source{
\strong{M39 Analysis and Presentation of Cumulative Antimicrobial Susceptibility Test Data, 4th Edition}, 2014, \emph{Clinical and Laboratory Standards Institute (CLSI)}. \url{https://clsi.org/standards/products/microbiology/documents/m39/}.
}
\usage{
S(ab1, ab2 = NULL, minimum = 30, as_percent = FALSE)
rsi_R(ab1, minimum = 30, as_percent = FALSE)
SI(ab1, ab2 = NULL, minimum = 30, as_percent = FALSE)
rsi_IR(ab1, minimum = 30, as_percent = FALSE)
IR(ab1, minimum = 30, as_percent = FALSE)
rsi_I(ab1, minimum = 30, as_percent = FALSE)
R(ab1, minimum = 30, as_percent = FALSE)
rsi_SI(ab1, ab2 = NULL, minimum = 30, as_percent = FALSE)
n_rsi(ab1, ab2 = NULL)
rsi_S(ab1, ab2 = NULL, minimum = 30, as_percent = FALSE)
resistance(ab1, include_I = TRUE, minimum = 30, as_percent = FALSE)
intermediate(ab1, minimum = 30, as_percent = FALSE)
susceptibility(ab1, ab2 = NULL, include_I = FALSE, minimum = 30,
as_percent = FALSE)
rsi(ab1, ab2 = NA, interpretation = "IR", minimum = 30,
as_percent = FALSE, info = FALSE, warning = TRUE)
rsi_n(ab1, ab2 = NULL)
n_rsi(ab1, ab2 = NULL)
}
\arguments{
\item{ab1}{vector of antibiotic interpretations, they will be transformed internally with \code{\link{as.rsi}}}
\item{ab2}{like \code{ab}, a vector of antibiotic interpretations. Use this to calculate (the lack of) co-resistance: the probability where one of two drugs have a susceptible result. See Examples.}
\item{minimum}{minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA}. The default number of \code{30} isolates is advised by the CLSI as best practice, see Source.}
\item{as_percent}{logical to indicate whether the output must be returned as percent (text), will else be a double}
\item{ab2}{like \code{ab}, a vector of antibiotic interpretations. Use this to calculate (the lack of) co-resistance: the probability where one of two drugs have a susceptible result. See Examples.}
\item{include_I}{logical to indicate whether antimicrobial interpretations of "I" should be included}
\item{interpretation}{antimicrobial interpretation}
\item{info}{\emph{DEPRECATED} calculate the amount of available isolates and print it, like \code{n = 423}}
\item{warning}{\emph{DEPRECATED} show a warning when the available amount of isolates is below \code{minimum}}
}
\value{
Double or, when \code{as_percent = TRUE}, a character.
}
\description{
These functions can be used to calculate the (co-)resistance of microbial isolates (i.e. percentage S, SI, IR or R). All functions can be used in \code{dplyr}s \code{\link[dplyr]{summarise}} and support grouped variables, see \emph{Examples}. \cr\cr
\code{R} and \code{IR} can be used to calculate resistance, \code{S} and \code{SI} can be used to calculate susceptibility.\cr
\code{n_rsi} counts all cases where antimicrobial interpretations are available.
These functions can be used to calculate the (co-)resistance of microbial isolates (i.e. percentage S, SI, I, IR or R). All functions can be used in \code{dplyr}s \code{\link[dplyr]{summarise}} and support grouped variables, see \emph{Examples}. \cr\cr
\code{rsi_R} and \code{rsi_IR} can be used to calculate resistance, \code{rsi_S} and \code{rsi_SI} can be used to calculate susceptibility.\cr
\code{rsi_n} counts all cases where antimicrobial interpretations are available.
}
\details{
\strong{Remember that you should filter your table to let it contain only first isolates!} Use \code{\link{first_isolate}} to determine them in your data set.
The functions \code{resistance} and \code{susceptibility} are wrappers around \code{IR} and \code{S}, respectively. All functions except \code{rsi} use hybrid evaluation (i.e. using C++), which makes these functions 20-30 times faster than the old \code{rsi} function. This latter function is still available for backwards compatibility but is deprecated.
The functions \code{resistance} and \code{susceptibility} are wrappers around \code{rsi_IR} and \code{rsi_S}, respectively. All functions use hybrid evaluation (i.e. using C++), which makes these functions 20-30 times faster than the old \code{\link{rsi}} function. This latter function is still available for backwards compatibility but is deprecated.
\if{html}{
\cr\cr
To calculate the probability (\emph{p}) of susceptibility of one antibiotic, we use this formula:
@ -76,44 +75,52 @@ The functions \code{resistance} and \code{susceptibility} are wrappers around \c
}
\examples{
# Calculate resistance
R(septic_patients$amox)
IR(septic_patients$amox)
rsi_R(septic_patients$amox)
rsi_IR(septic_patients$amox)
# Or susceptibility
S(septic_patients$amox)
SI(septic_patients$amox)
rsi_S(septic_patients$amox)
rsi_SI(septic_patients$amox)
# Since n_rsi counts available isolates (and is used as denominator),
# you can calculate back to e.g. count resistant isolates:
IR(septic_patients$amox) * n_rsi(septic_patients$amox)
rsi_IR(septic_patients$amox) * n_rsi(septic_patients$amox)
library(dplyr)
septic_patients \%>\%
group_by(hospital_id) \%>\%
summarise(p = S(cipr),
n = n_rsi(cipr)) # n_rsi works like n_distinct in dplyr
# Calculate co-resistance between amoxicillin/clav acid and gentamicin,
# so we can see that combination therapy does a lot more than mono therapy:
S(septic_patients$amcl) # p = 67.3\%
n_rsi(septic_patients$amcl) # n = 1570
S(septic_patients$gent) # p = 74.0\%
n_rsi(septic_patients$gent) # n = 1842
with(septic_patients,
S(amcl, gent)) # p = 92.1\%
with(septic_patients,
n_rsi(amcl, gent)) # n = 1504
summarise(p = rsi_S(cipr),
n = rsi_n(cipr)) # n_rsi works like n_distinct in dplyr
septic_patients \%>\%
group_by(hospital_id) \%>\%
summarise(cipro_p = S(cipr, as_percent = TRUE),
cipro_n = n_rsi(cipr),
genta_p = S(gent, as_percent = TRUE),
genta_n = n_rsi(gent),
combination_p = S(cipr, gent, as_percent = TRUE),
combination_n = n_rsi(cipr, gent))
summarise(R = rsi_R(cipr, as_percent = TRUE),
I = rsi_I(cipr, as_percent = TRUE),
S = rsi_S(cipr, as_percent = TRUE),
n = rsi_n(cipr), # also: n_rsi, works like n_distinct in dplyr
total = n()) # this is the length, NOT the amount of tested isolates
# Calculate co-resistance between amoxicillin/clav acid and gentamicin,
# so we can see that combination therapy does a lot more than mono therapy:
rsi_S(septic_patients$amcl) # S = 67.3\%
rsi_n(septic_patients$amcl) # n = 1570
rsi_S(septic_patients$gent) # S = 74.0\%
rsi_n(septic_patients$gent) # n = 1842
with(septic_patients,
rsi_S(amcl, gent)) # S = 92.1\%
with(septic_patients, # n = 1504
rsi_n(amcl, gent))
septic_patients \%>\%
group_by(hospital_id) \%>\%
summarise(cipro_p = rsi_S(cipr, as_percent = TRUE),
cipro_n = rsi_n(cipr),
genta_p = rsi_S(gent, as_percent = TRUE),
genta_n = rsi_n(gent),
combination_p = rsi_S(cipr, gent, as_percent = TRUE),
combination_n = rsi_n(cipr, gent))
\dontrun{
@ -121,8 +128,8 @@ septic_patients \%>\%
my_table \%>\%
filter(first_isolate == TRUE,
genus == "Helicobacter") \%>\%
summarise(p = S(amox, metr), # amoxicillin with metronidazole
n = n_rsi(amox, metr))
summarise(p = rsi_S(amox, metr), # amoxicillin with metronidazole
n = rsi_n(amox, metr))
}
}
\keyword{antibiotics}

View File

@ -17,6 +17,17 @@ BEGIN_RCPP
return rcpp_result_gen;
END_RCPP
}
// rsi_calc_I
int rsi_calc_I(DoubleVector x);
RcppExport SEXP _AMR_rsi_calc_I(SEXP xSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< DoubleVector >::type x(xSEXP);
rcpp_result_gen = Rcpp::wrap(rsi_calc_I(x));
return rcpp_result_gen;
END_RCPP
}
// rsi_calc_R
int rsi_calc_R(DoubleVector x, bool include_I);
RcppExport SEXP _AMR_rsi_calc_R(SEXP xSEXP, SEXP include_ISEXP) {
@ -32,6 +43,7 @@ END_RCPP
static const R_CallMethodDef CallEntries[] = {
{"_AMR_rsi_calc_S", (DL_FUNC) &_AMR_rsi_calc_S, 2},
{"_AMR_rsi_calc_I", (DL_FUNC) &_AMR_rsi_calc_I, 1},
{"_AMR_rsi_calc_R", (DL_FUNC) &_AMR_rsi_calc_R, 2},
{NULL, NULL, 0}
};

View File

@ -1,6 +1,4 @@
#include <Rcpp.h>
// #include <functional> // for std::less_equal and std::greater_equal
// #include <algorithm> // for count_if
using namespace Rcpp;
@ -12,6 +10,14 @@ int rsi_calc_S(DoubleVector x, bool include_I) {
1 + include_I));
}
// [[Rcpp::export]]
int rsi_calc_I(DoubleVector x) {
return count_if(x.begin(),
x.end(),
bind2nd(std::equal_to<double>(),
2));
}
// [[Rcpp::export]]
int rsi_calc_R(DoubleVector x, bool include_I) {
return count_if(x.begin(),

View File

@ -1,19 +1,23 @@
context("resistance.R")
context("rsi_IR.R")
test_that("resistance works", {
# check shortcuts
expect_equal(resistance(septic_patients$amox, include_I = TRUE),
IR(septic_patients$amox))
rsi_IR(septic_patients$amox))
expect_equal(resistance(septic_patients$amox, include_I = FALSE),
R(septic_patients$amox))
rsi_R(septic_patients$amox))
expect_equal(intermediate(septic_patients$amox),
rsi_I(septic_patients$amox))
expect_equal(susceptibility(septic_patients$amox, include_I = TRUE),
SI(septic_patients$amox))
rsi_SI(septic_patients$amox))
expect_equal(susceptibility(septic_patients$amox, include_I = FALSE),
S(septic_patients$amox))
rsi_S(septic_patients$amox))
# amox resistance in `septic_patients` should be around 66.33%
expect_equal(resistance(septic_patients$amox, include_I = TRUE), 0.6633, tolerance = 0.0001)
expect_equal(susceptibility(septic_patients$amox, include_I = FALSE), 1 - 0.6633, tolerance = 0.0001)
# amox resistance in `septic_patients`
expect_equal(rsi_R(septic_patients$amox), 0.6603, tolerance = 0.0001)
expect_equal(rsi_I(septic_patients$amox), 0.0030, tolerance = 0.0001)
expect_equal(1 - rsi_R(septic_patients$amox) - rsi_I(septic_patients$amox),
rsi_S(septic_patients$amox))
# pita+genta susceptibility around 98.09%
expect_equal(susceptibility(septic_patients$pita,
@ -26,6 +30,18 @@ test_that("resistance works", {
0.9535,
tolerance = 0.0001)
# percentages
expect_equal(septic_patients %>%
group_by(hospital_id) %>%
summarise(R = rsi_R(cipr, as_percent = TRUE),
I = rsi_I(cipr, as_percent = TRUE),
S = rsi_S(cipr, as_percent = TRUE),
n = rsi_n(cipr),
total = n()) %>%
pull(n) %>%
sum(),
1404)
# count of cases
expect_equal(septic_patients %>%
group_by(hospital_id) %>%
@ -34,7 +50,7 @@ test_that("resistance works", {
genta_p = susceptibility(gent, as_percent = TRUE),
genta_n = n_rsi(gent),
combination_p = susceptibility(cipr, gent, as_percent = TRUE),
combination_n = n_rsi(cipr, gent)) %>%
combination_n = rsi_n(cipr, gent)) %>%
pull(combination_n),
c(202, 482, 201, 499))
@ -45,22 +61,29 @@ test_that("resistance works", {
# check for errors
expect_error(IR(septic_patients %>% select(amox, amcl)))
expect_error(IR("test", minimum = "test"))
expect_error(IR("test", as_percent = "test"))
expect_error(S("test", minimum = "test"))
expect_error(S("test", as_percent = "test"))
expect_error(S(septic_patients %>% select(amox, amcl)))
expect_error(S("R", septic_patients %>% select(amox, amcl)))
expect_error(rsi_IR(septic_patients %>% select(amox, amcl)))
expect_error(rsi_IR("test", minimum = "test"))
expect_error(rsi_IR("test", as_percent = "test"))
expect_error(rsi_I(septic_patients %>% select(amox, amcl)))
expect_error(rsi_I("test", minimum = "test"))
expect_error(rsi_I("test", as_percent = "test"))
expect_error(rsi_S("test", minimum = "test"))
expect_error(rsi_S("test", as_percent = "test"))
expect_error(rsi_S(septic_patients %>% select(amox, amcl)))
expect_error(rsi_S("R", septic_patients %>% select(amox, amcl)))
# check too low amount of isolates
expect_identical(IR(septic_patients$amox, minimum = nrow(septic_patients) + 1),
expect_identical(rsi_R(septic_patients$amox, minimum = nrow(septic_patients) + 1),
NA)
expect_identical(S(septic_patients$amox, minimum = nrow(septic_patients) + 1),
expect_identical(rsi_I(septic_patients$amox, minimum = nrow(septic_patients) + 1),
NA)
expect_identical(rsi_S(septic_patients$amox, minimum = nrow(septic_patients) + 1),
NA)
# warning for speed loss
expect_warning(S(septic_patients$amcl, as.character(septic_patients$gent)))
expect_warning(rsi_R(as.character(septic_patients$gent)))
expect_warning(rsi_I(as.character(septic_patients$gent)))
expect_warning(rsi_S(septic_patients$amcl, as.character(septic_patients$gent)))
})