mirror of
https://github.com/msberends/AMR.git
synced 2024-12-26 20:06:11 +01:00
new algorithm key abs
This commit is contained in:
parent
967ee86757
commit
5cb9c541f8
@ -1,5 +1,5 @@
|
|||||||
Package: AMR
|
Package: AMR
|
||||||
Version: 0.2.0.9012
|
Version: 0.2.0.9013
|
||||||
Date: 2018-07-17
|
Date: 2018-07-17
|
||||||
Title: Antimicrobial Resistance Analysis
|
Title: Antimicrobial Resistance Analysis
|
||||||
Authors@R: c(
|
Authors@R: c(
|
||||||
|
@ -51,6 +51,7 @@ export(interpretive_reading)
|
|||||||
export(is.mic)
|
export(is.mic)
|
||||||
export(is.rsi)
|
export(is.rsi)
|
||||||
export(key_antibiotics)
|
export(key_antibiotics)
|
||||||
|
export(key_antibiotics_equal)
|
||||||
export(kurtosis)
|
export(kurtosis)
|
||||||
export(left_join_microorganisms)
|
export(left_join_microorganisms)
|
||||||
export(like)
|
export(like)
|
||||||
|
3
NEWS.md
3
NEWS.md
@ -1,6 +1,9 @@
|
|||||||
# 0.2.0.90xx (development version)
|
# 0.2.0.90xx (development version)
|
||||||
#### New
|
#### New
|
||||||
* **BREAKING**: `rsi_df` was removed in favour of new functions `resistance` and `susceptibility`. Now, all functions used to calculate resistance (`resistance` and `susceptibility`) or count isolates (`n_rsi`) use **hybrid evaluation**. This means calculations are not done in R directly but rather in C++ using the `Rcpp` package, making them 25 to 30 times faster. The function `rsi` still works, but is deprecated.
|
* **BREAKING**: `rsi_df` was removed in favour of new functions `resistance` and `susceptibility`. Now, all functions used to calculate resistance (`resistance` and `susceptibility`) or count isolates (`n_rsi`) use **hybrid evaluation**. This means calculations are not done in R directly but rather in C++ using the `Rcpp` package, making them 25 to 30 times faster. The function `rsi` still works, but is deprecated.
|
||||||
|
* **BREAKING**: the methodology for determining first weighted isolates was changed. The antibiotics (call *key antibiotics*) that are compared between isolated to include more first isolates (called first *weighted* isolates) are now as follows:
|
||||||
|
* Gram-positive: amoxicillin, amoxicillin/clavlanic acid, cefuroxime, piperacillin/tazobactam, ciprofloxacin, trimethoprim/sulfamethoxazole, vancomycin, teicoplanin, tetracycline, erythromycin, oxacillin, rifampicin
|
||||||
|
* Gram-negative: amoxicillin, amoxicillin/clavlanic acid, cefuroxime, piperacillin/tazobactam, ciprofloxacin, trimethoprim/sulfamethoxazole, gentamicin, tobramycin, colistin, cefotaxime, ceftazidime, meropenem
|
||||||
* Support for Addins menu in RStudio to quickly insert `%in%` or `%like%` (and give them keyboard shortcuts), or to view the datasets that come with this package
|
* Support for Addins menu in RStudio to quickly insert `%in%` or `%like%` (and give them keyboard shortcuts), or to view the datasets that come with this package
|
||||||
* For convience, new descriptive statistical functions `kurtosis` and `skewness` that are lacking in base R - they are generic functions and have support for vectors, data.frames and matrices
|
* For convience, new descriptive statistical functions `kurtosis` and `skewness` that are lacking in base R - they are generic functions and have support for vectors, data.frames and matrices
|
||||||
* Function `g.test` as added to perform the Χ<sup>2</sup> distributed [*G*-test](https://en.wikipedia.org/wiki/G-test), which use is the same as `chisq.test`
|
* Function `g.test` as added to perform the Χ<sup>2</sup> distributed [*G*-test](https://en.wikipedia.org/wiki/G-test), which use is the same as `chisq.test`
|
||||||
|
@ -40,13 +40,16 @@
|
|||||||
#' @param col_species (deprecated, use \code{col_bactid} instead) column name of the species of the microorganisms
|
#' @param col_species (deprecated, use \code{col_bactid} instead) column name of the species of the microorganisms
|
||||||
#' @details \strong{WHY THIS IS SO IMPORTANT} \cr
|
#' @details \strong{WHY THIS IS SO IMPORTANT} \cr
|
||||||
#' To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode \href{https://www.ncbi.nlm.nih.gov/pubmed/17304462}{[1]}. If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all \emph{S. aureus} isolates would be overestimated, because you included this MRSA more than once. It would be \href{https://en.wikipedia.org/wiki/Selection_bias}{selection bias}.
|
#' To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode \href{https://www.ncbi.nlm.nih.gov/pubmed/17304462}{[1]}. If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all \emph{S. aureus} isolates would be overestimated, because you included this MRSA more than once. It would be \href{https://en.wikipedia.org/wiki/Selection_bias}{selection bias}.
|
||||||
|
#' @section Key antibiotics:
|
||||||
|
#' There are two ways to determine whether isolates can be included as first \emph{weighted} isolates: \cr
|
||||||
#'
|
#'
|
||||||
#' \strong{DETERMINING WEIGHTED ISOLATES} \cr
|
|
||||||
#' \strong{1. Using} \code{type = "keyantibiotics"} \strong{and parameter} \code{ignore_I} \cr
|
#' \strong{1. Using} \code{type = "keyantibiotics"} \strong{and parameter} \code{ignore_I} \cr
|
||||||
#' To determine weighted isolates, the difference between key antibiotics will be checked. Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With \code{ignore_I = FALSE}, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. \cr
|
#' Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With \code{ignore_I = FALSE}, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. \cr
|
||||||
|
#'
|
||||||
#' \strong{2. Using} \code{type = "points"} \strong{and parameter} \code{points_threshold} \cr
|
#' \strong{2. Using} \code{type = "points"} \strong{and parameter} \code{points_threshold} \cr
|
||||||
#' To determine weighted isolates, difference between antimicrobial interpretations will be measured with points. A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds \code{points_threshold}, an isolate will be (re)selected as a first weighted isolate. This method is being used by the Infection Prevention department (Dr M. Lokate) of the University Medical Center Groningen (UMCG).
|
#' A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds \code{points_threshold}, an isolate will be (re)selected as a first weighted isolate.
|
||||||
#' @keywords isolate isolates first
|
#' @keywords isolate isolates first
|
||||||
|
#' @seealso \code{\link{keyantibiotics}}
|
||||||
#' @export
|
#' @export
|
||||||
#' @importFrom dplyr arrange_at lag between row_number filter mutate arrange
|
#' @importFrom dplyr arrange_at lag between row_number filter mutate arrange
|
||||||
#' @return A vector to add to table, see Examples.
|
#' @return A vector to add to table, see Examples.
|
||||||
@ -401,205 +404,3 @@ first_isolate <- function(tbl,
|
|||||||
all_first
|
all_first
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#' Key antibiotics based on bacteria ID
|
|
||||||
#'
|
|
||||||
#' @param tbl table with antibiotics coloms, like \code{amox} and \code{amcl}.
|
|
||||||
#' @inheritParams first_isolate
|
|
||||||
#' @param amcl,amox,cfot,cfta,cftr,cfur,cipr,clar,clin,clox,doxy,gent,line,mero,peni,pita,rifa,teic,trsu,vanc column names of antibiotics, case-insensitive
|
|
||||||
#' @export
|
|
||||||
#' @importFrom dplyr %>% mutate if_else
|
|
||||||
#' @return Character of length 1.
|
|
||||||
#' @seealso \code{\link{mo_property}} \code{\link{antibiotics}}
|
|
||||||
#' @examples
|
|
||||||
#' \donttest{
|
|
||||||
#' #' # set key antibiotics to a new variable
|
|
||||||
#' tbl$keyab <- key_antibiotics(tbl)
|
|
||||||
#' }
|
|
||||||
key_antibiotics <- function(tbl,
|
|
||||||
col_bactid = 'bactid',
|
|
||||||
info = TRUE,
|
|
||||||
amcl = 'amcl',
|
|
||||||
amox = 'amox',
|
|
||||||
cfot = 'cfot',
|
|
||||||
cfta = 'cfta',
|
|
||||||
cftr = 'cftr',
|
|
||||||
cfur = 'cfur',
|
|
||||||
cipr = 'cipr',
|
|
||||||
clar = 'clar',
|
|
||||||
clin = 'clin',
|
|
||||||
clox = 'clox',
|
|
||||||
doxy = 'doxy',
|
|
||||||
gent = 'gent',
|
|
||||||
line = 'line',
|
|
||||||
mero = 'mero',
|
|
||||||
peni = 'peni',
|
|
||||||
pita = 'pita',
|
|
||||||
rifa = 'rifa',
|
|
||||||
teic = 'teic',
|
|
||||||
trsu = 'trsu',
|
|
||||||
vanc = 'vanc') {
|
|
||||||
|
|
||||||
keylist <- character(length = nrow(tbl))
|
|
||||||
|
|
||||||
if (!col_bactid %in% colnames(tbl)) {
|
|
||||||
stop('Column ', col_bactid, ' not found.', call. = FALSE)
|
|
||||||
}
|
|
||||||
|
|
||||||
# check columns
|
|
||||||
col.list <- c(amox, cfot, cfta, cftr, cfur, cipr, clar,
|
|
||||||
clin, clox, doxy, gent, line, mero, peni,
|
|
||||||
pita, rifa, teic, trsu, vanc)
|
|
||||||
col.list <- check_available_columns(tbl = tbl, col.list = col.list, info = info)
|
|
||||||
amox <- col.list[amox]
|
|
||||||
cfot <- col.list[cfot]
|
|
||||||
cfta <- col.list[cfta]
|
|
||||||
cftr <- col.list[cftr]
|
|
||||||
cfur <- col.list[cfur]
|
|
||||||
cipr <- col.list[cipr]
|
|
||||||
clar <- col.list[clar]
|
|
||||||
clin <- col.list[clin]
|
|
||||||
clox <- col.list[clox]
|
|
||||||
doxy <- col.list[doxy]
|
|
||||||
gent <- col.list[gent]
|
|
||||||
line <- col.list[line]
|
|
||||||
mero <- col.list[mero]
|
|
||||||
peni <- col.list[peni]
|
|
||||||
pita <- col.list[pita]
|
|
||||||
rifa <- col.list[rifa]
|
|
||||||
teic <- col.list[teic]
|
|
||||||
trsu <- col.list[trsu]
|
|
||||||
vanc <- col.list[vanc]
|
|
||||||
|
|
||||||
# join microorganisms
|
|
||||||
tbl <- tbl %>% left_join_microorganisms(col_bactid)
|
|
||||||
|
|
||||||
tbl$key_ab <- NA_character_
|
|
||||||
|
|
||||||
# Staphylococcus
|
|
||||||
list_ab <- c(clox, trsu, teic, vanc, doxy, line, clar, rifa)
|
|
||||||
list_ab <- list_ab[list_ab %in% colnames(tbl)]
|
|
||||||
tbl <- tbl %>% mutate(key_ab =
|
|
||||||
if_else(genus == 'Staphylococcus',
|
|
||||||
apply(X = tbl[, list_ab],
|
|
||||||
MARGIN = 1,
|
|
||||||
FUN = function(x) paste(x, collapse = "")),
|
|
||||||
key_ab))
|
|
||||||
|
|
||||||
# Rest of Gram +
|
|
||||||
list_ab <- c(peni, amox, teic, vanc, clin, line, clar, trsu)
|
|
||||||
list_ab <- list_ab[list_ab %in% colnames(tbl)]
|
|
||||||
tbl <- tbl %>% mutate(key_ab =
|
|
||||||
if_else(gramstain %like% '^Positive ',
|
|
||||||
apply(X = tbl[, list_ab],
|
|
||||||
MARGIN = 1,
|
|
||||||
FUN = function(x) paste(x, collapse = "")),
|
|
||||||
key_ab))
|
|
||||||
|
|
||||||
# Gram -
|
|
||||||
list_ab <- c(amox, amcl, pita, cfur, cfot, cfta, cftr, mero, cipr, trsu, gent)
|
|
||||||
list_ab <- list_ab[list_ab %in% colnames(tbl)]
|
|
||||||
tbl <- tbl %>% mutate(key_ab =
|
|
||||||
if_else(gramstain %like% '^Negative ',
|
|
||||||
apply(X = tbl[, list_ab],
|
|
||||||
MARGIN = 1,
|
|
||||||
FUN = function(x) paste(x, collapse = "")),
|
|
||||||
key_ab))
|
|
||||||
|
|
||||||
# format
|
|
||||||
tbl <- tbl %>%
|
|
||||||
mutate(key_ab = gsub('(NA|NULL)', '-', key_ab) %>% toupper())
|
|
||||||
|
|
||||||
tbl$key_ab
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#' @importFrom dplyr progress_estimated %>%
|
|
||||||
#' @noRd
|
|
||||||
key_antibiotics_equal <- function(x,
|
|
||||||
y,
|
|
||||||
type = c("keyantibiotics", "points"),
|
|
||||||
ignore_I = TRUE,
|
|
||||||
points_threshold = 2,
|
|
||||||
info = FALSE) {
|
|
||||||
# x is active row, y is lag
|
|
||||||
type <- type[1]
|
|
||||||
|
|
||||||
if (length(x) != length(y)) {
|
|
||||||
stop('Length of `x` and `y` must be equal.')
|
|
||||||
}
|
|
||||||
|
|
||||||
result <- logical(length(x))
|
|
||||||
|
|
||||||
if (type == "keyantibiotics") {
|
|
||||||
if (ignore_I == TRUE) {
|
|
||||||
# evaluation using regular expression will treat '?' as any character
|
|
||||||
# so I is actually ignored then
|
|
||||||
x <- gsub('I', '?', x, ignore.case = TRUE)
|
|
||||||
y <- gsub('I', '?', y, ignore.case = TRUE)
|
|
||||||
}
|
|
||||||
for (i in 1:length(x)) {
|
|
||||||
result[i] <- grepl(x = x[i],
|
|
||||||
pattern = y[i],
|
|
||||||
ignore.case = TRUE) |
|
|
||||||
grepl(x = y[i],
|
|
||||||
pattern = x[i],
|
|
||||||
ignore.case = TRUE)
|
|
||||||
}
|
|
||||||
return(result)
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (info == TRUE) {
|
|
||||||
p <- dplyr::progress_estimated(length(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 1:length(x)) {
|
|
||||||
|
|
||||||
if (info == TRUE) {
|
|
||||||
p$tick()$print()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is.na(x[i])) {
|
|
||||||
x[i] <- ''
|
|
||||||
}
|
|
||||||
if (is.na(y[i])) {
|
|
||||||
y[i] <- ''
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nchar(x[i]) != nchar(y[i])) {
|
|
||||||
|
|
||||||
result[i] <- FALSE
|
|
||||||
|
|
||||||
} else if (x[i] == '' & y[i] == '') {
|
|
||||||
|
|
||||||
result[i] <- TRUE
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
x2 <- strsplit(x[i], "")[[1]]
|
|
||||||
y2 <- strsplit(y[i], "")[[1]]
|
|
||||||
|
|
||||||
if (type == 'points') {
|
|
||||||
# count points for every single character:
|
|
||||||
# - no change is 0 points
|
|
||||||
# - I <-> S|R is 0.5 point
|
|
||||||
# - S|R <-> R|S is 1 point
|
|
||||||
# use the levels of as.rsi (S = 1, I = 2, R = 3)
|
|
||||||
|
|
||||||
suppressWarnings(x2 <- x2 %>% as.rsi() %>% as.double())
|
|
||||||
suppressWarnings(y2 <- y2 %>% as.rsi() %>% as.double())
|
|
||||||
|
|
||||||
points <- (x2 - y2) %>% abs() %>% sum(na.rm = TRUE)
|
|
||||||
result[i] <- ((points / 2) >= points_threshold)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
stop('`', type, '` is not a valid value for type, must be "points" or "keyantibiotics". See ?first_isolate.')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (info == TRUE) {
|
|
||||||
cat('\n')
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
233
R/key_antibiotics.R
Normal file
233
R/key_antibiotics.R
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
# ==================================================================== #
|
||||||
|
# TITLE #
|
||||||
|
# Antimicrobial Resistance (AMR) Analysis #
|
||||||
|
# #
|
||||||
|
# AUTHORS #
|
||||||
|
# Berends MS (m.s.berends@umcg.nl), Luz CF (c.f.luz@umcg.nl) #
|
||||||
|
# #
|
||||||
|
# LICENCE #
|
||||||
|
# This program is free software; you can redistribute it and/or modify #
|
||||||
|
# it under the terms of the GNU General Public License version 2.0, #
|
||||||
|
# as published by the Free Software Foundation. #
|
||||||
|
# #
|
||||||
|
# This program is distributed in the hope that it will be useful, #
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||||
|
# GNU General Public License for more details. #
|
||||||
|
# ==================================================================== #
|
||||||
|
|
||||||
|
#' Key antibiotics for first \emph{weighted} isolates
|
||||||
|
#'
|
||||||
|
#' These function can be used to determine first isolates (see \code{\link{first_isolate}}). Using key antibiotics to determine first isolates is more reliable than without key antibiotics. These selected isolates will then be called first \emph{weighted} isolates.
|
||||||
|
#' @param tbl table with antibiotics coloms, like \code{amox} and \code{amcl}.
|
||||||
|
#' @inheritParams first_isolate
|
||||||
|
#' @param amcl,amox,cfot,cfta,cfur,cipr,coli,eryt,gent,mero,oxac,pita,rifa,teic,tetr,tobr,trsu,vanc column names of antibiotics, case-insensitive
|
||||||
|
#' @details The function \code{key_antibiotics} returns a character vector with antibiotic results.
|
||||||
|
#'
|
||||||
|
#' The antibiotics that are used for \strong{Gram positive bacteria} are (colum names): \cr
|
||||||
|
#' amox, amcl, cfur, pita, cipr, trsu, vanc, teic, tetr, eryt, oxac, rifa.
|
||||||
|
#'
|
||||||
|
#' The antibiotics that are used for \strong{Gram negative bacteria} are (colum names): \cr
|
||||||
|
#' amox, amcl, cfur, pita, cipr, trsu, gent, tobr, coli, cfot, cfta, mero.
|
||||||
|
#'
|
||||||
|
#'
|
||||||
|
#' The function \code{key_antibiotics_equal} checks the characters returned by \code{key_antibiotics} for equality, and returns a logical value.
|
||||||
|
#' @inheritSection first_isolate Key antibiotics
|
||||||
|
#' @rdname key_antibiotics
|
||||||
|
#' @export
|
||||||
|
#' @importFrom dplyr %>% mutate if_else
|
||||||
|
#' @seealso \code{\link{first_isolate}}
|
||||||
|
#' @examples
|
||||||
|
#' \dontrun{
|
||||||
|
#' # set key antibiotics to a new variable
|
||||||
|
#' tbl$keyab <- key_antibiotics(tbl)
|
||||||
|
#'
|
||||||
|
#' # add regular first isolates
|
||||||
|
#' tbl$first_isolate <-
|
||||||
|
#' first_isolate(tbl)
|
||||||
|
#'
|
||||||
|
#' # add first WEIGHTED isolates using key antibiotics
|
||||||
|
#' tbl$first_isolate_weighed <-
|
||||||
|
#' first_isolate(tbl,
|
||||||
|
#' col_keyantibiotics = 'keyab')
|
||||||
|
#' }
|
||||||
|
key_antibiotics <- function(tbl,
|
||||||
|
col_bactid = "bactid",
|
||||||
|
amcl = "amcl",
|
||||||
|
amox = "amox",
|
||||||
|
cfot = "cfot",
|
||||||
|
cfta = "cfta",
|
||||||
|
cfur = "cfur",
|
||||||
|
cipr = "cipr",
|
||||||
|
coli = "coli",
|
||||||
|
eryt = "eryt",
|
||||||
|
gent = "gent",
|
||||||
|
mero = "mero",
|
||||||
|
oxac = "oxac",
|
||||||
|
pita = "pita",
|
||||||
|
rifa = "rifa",
|
||||||
|
teic = "teic",
|
||||||
|
tetr = "tetr",
|
||||||
|
tobr = "tobr",
|
||||||
|
trsu = "trsu",
|
||||||
|
vanc = "vanc",
|
||||||
|
info = TRUE) {
|
||||||
|
|
||||||
|
if (!col_bactid %in% colnames(tbl)) {
|
||||||
|
stop('Column ', col_bactid, ' not found.', call. = FALSE)
|
||||||
|
}
|
||||||
|
|
||||||
|
# check columns
|
||||||
|
col.list <- c(amcl, amox, cfot, cfta, cfur, cipr,
|
||||||
|
coli, eryt, gent, mero, oxac, pita,
|
||||||
|
rifa, teic, tetr, tobr, trsu, vanc)
|
||||||
|
col.list <- check_available_columns(tbl = tbl, col.list = col.list, info = info)
|
||||||
|
amcl <- col.list[amcl]
|
||||||
|
amox <- col.list[amox]
|
||||||
|
cfot <- col.list[cfot]
|
||||||
|
cfta <- col.list[cfta]
|
||||||
|
cfur <- col.list[cfur]
|
||||||
|
cipr <- col.list[cipr]
|
||||||
|
coli <- col.list[coli]
|
||||||
|
eryt <- col.list[eryt]
|
||||||
|
gent <- col.list[gent]
|
||||||
|
mero <- col.list[mero]
|
||||||
|
oxac <- col.list[oxac]
|
||||||
|
pita <- col.list[pita]
|
||||||
|
rifa <- col.list[rifa]
|
||||||
|
teic <- col.list[teic]
|
||||||
|
tetr <- col.list[tetr]
|
||||||
|
tobr <- col.list[tobr]
|
||||||
|
trsu <- col.list[trsu]
|
||||||
|
vanc <- col.list[vanc]
|
||||||
|
|
||||||
|
gram_positive = c(amox, amcl, cfur, pita, cipr, trsu,
|
||||||
|
# specific for G+:
|
||||||
|
vanc, teic, tetr, eryt, oxac, rifa)
|
||||||
|
gram_positive <- gram_positive[!is.na(gram_positive)]
|
||||||
|
|
||||||
|
gram_negative = c(amox, amcl, cfur, pita, cipr, trsu,
|
||||||
|
# specific for G-:
|
||||||
|
gent, tobr, coli, cfot, cfta, mero)
|
||||||
|
gram_negative <- gram_negative[!is.na(gram_negative)]
|
||||||
|
|
||||||
|
# join microorganisms
|
||||||
|
tbl <- tbl %>% left_join_microorganisms(col_bactid)
|
||||||
|
|
||||||
|
tbl$key_ab <- NA_character_
|
||||||
|
|
||||||
|
# Gram +
|
||||||
|
tbl <- tbl %>% mutate(key_ab =
|
||||||
|
if_else(gramstain %like% '^Positive ',
|
||||||
|
apply(X = tbl[, gram_positive],
|
||||||
|
MARGIN = 1,
|
||||||
|
FUN = function(x) paste(x, collapse = "")),
|
||||||
|
key_ab))
|
||||||
|
|
||||||
|
# Gram -
|
||||||
|
tbl <- tbl %>% mutate(key_ab =
|
||||||
|
if_else(gramstain %like% '^Negative ',
|
||||||
|
apply(X = tbl[, gram_negative],
|
||||||
|
MARGIN = 1,
|
||||||
|
FUN = function(x) paste(x, collapse = "")),
|
||||||
|
key_ab))
|
||||||
|
|
||||||
|
# format
|
||||||
|
key_abs <- tbl %>%
|
||||||
|
pull(key_ab) %>%
|
||||||
|
gsub('(NA|NULL)', '-', .)
|
||||||
|
|
||||||
|
key_abs
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#' @importFrom dplyr progress_estimated %>%
|
||||||
|
#' @rdname key_antibiotics
|
||||||
|
#' @export
|
||||||
|
key_antibiotics_equal <- function(x,
|
||||||
|
y,
|
||||||
|
type = c("keyantibiotics", "points"),
|
||||||
|
ignore_I = TRUE,
|
||||||
|
points_threshold = 2,
|
||||||
|
info = FALSE) {
|
||||||
|
# x is active row, y is lag
|
||||||
|
type <- type[1]
|
||||||
|
|
||||||
|
if (length(x) != length(y)) {
|
||||||
|
stop('Length of `x` and `y` must be equal.')
|
||||||
|
}
|
||||||
|
|
||||||
|
result <- logical(length(x))
|
||||||
|
|
||||||
|
if (type == "keyantibiotics") {
|
||||||
|
if (ignore_I == TRUE) {
|
||||||
|
# evaluation using regular expression will treat '?' as any character
|
||||||
|
# so I is actually ignored then
|
||||||
|
x <- gsub('I', '?', x, ignore.case = TRUE)
|
||||||
|
y <- gsub('I', '?', y, ignore.case = TRUE)
|
||||||
|
}
|
||||||
|
for (i in 1:length(x)) {
|
||||||
|
result[i] <- grepl(x = x[i],
|
||||||
|
pattern = y[i],
|
||||||
|
ignore.case = TRUE) |
|
||||||
|
grepl(x = y[i],
|
||||||
|
pattern = x[i],
|
||||||
|
ignore.case = TRUE)
|
||||||
|
}
|
||||||
|
return(result)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (info == TRUE) {
|
||||||
|
p <- dplyr::progress_estimated(length(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in 1:length(x)) {
|
||||||
|
|
||||||
|
if (info == TRUE) {
|
||||||
|
p$tick()$print()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is.na(x[i])) {
|
||||||
|
x[i] <- ''
|
||||||
|
}
|
||||||
|
if (is.na(y[i])) {
|
||||||
|
y[i] <- ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nchar(x[i]) != nchar(y[i])) {
|
||||||
|
|
||||||
|
result[i] <- FALSE
|
||||||
|
|
||||||
|
} else if (x[i] == '' & y[i] == '') {
|
||||||
|
|
||||||
|
result[i] <- TRUE
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
x2 <- strsplit(x[i], "")[[1]]
|
||||||
|
y2 <- strsplit(y[i], "")[[1]]
|
||||||
|
|
||||||
|
if (type == 'points') {
|
||||||
|
# count points for every single character:
|
||||||
|
# - no change is 0 points
|
||||||
|
# - I <-> S|R is 0.5 point
|
||||||
|
# - S|R <-> R|S is 1 point
|
||||||
|
# use the levels of as.rsi (S = 1, I = 2, R = 3)
|
||||||
|
|
||||||
|
suppressWarnings(x2 <- x2 %>% as.rsi() %>% as.double())
|
||||||
|
suppressWarnings(y2 <- y2 %>% as.rsi() %>% as.double())
|
||||||
|
|
||||||
|
points <- (x2 - y2) %>% abs() %>% sum(na.rm = TRUE)
|
||||||
|
result[i] <- ((points / 2) >= points_threshold)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
stop('`', type, '` is not a valid value for type, must be "points" or "keyantibiotics". See ?first_isolate.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (info == TRUE) {
|
||||||
|
cat('\n')
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
@ -62,13 +62,18 @@ Determine first (weighted) isolates of all microorganisms of every patient per e
|
|||||||
\details{
|
\details{
|
||||||
\strong{WHY THIS IS SO IMPORTANT} \cr
|
\strong{WHY THIS IS SO IMPORTANT} \cr
|
||||||
To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode \href{https://www.ncbi.nlm.nih.gov/pubmed/17304462}{[1]}. If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all \emph{S. aureus} isolates would be overestimated, because you included this MRSA more than once. It would be \href{https://en.wikipedia.org/wiki/Selection_bias}{selection bias}.
|
To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode \href{https://www.ncbi.nlm.nih.gov/pubmed/17304462}{[1]}. If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all \emph{S. aureus} isolates would be overestimated, because you included this MRSA more than once. It would be \href{https://en.wikipedia.org/wiki/Selection_bias}{selection bias}.
|
||||||
|
|
||||||
\strong{DETERMINING WEIGHTED ISOLATES} \cr
|
|
||||||
\strong{1. Using} \code{type = "keyantibiotics"} \strong{and parameter} \code{ignore_I} \cr
|
|
||||||
To determine weighted isolates, the difference between key antibiotics will be checked. Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With \code{ignore_I = FALSE}, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. \cr
|
|
||||||
\strong{2. Using} \code{type = "points"} \strong{and parameter} \code{points_threshold} \cr
|
|
||||||
To determine weighted isolates, difference between antimicrobial interpretations will be measured with points. A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds \code{points_threshold}, an isolate will be (re)selected as a first weighted isolate. This method is being used by the Infection Prevention department (Dr M. Lokate) of the University Medical Center Groningen (UMCG).
|
|
||||||
}
|
}
|
||||||
|
\section{Key antibiotics}{
|
||||||
|
|
||||||
|
There are two ways to determine whether isolates can be included as first \emph{weighted} isolates: \cr
|
||||||
|
|
||||||
|
\strong{1. Using} \code{type = "keyantibiotics"} \strong{and parameter} \code{ignore_I} \cr
|
||||||
|
Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With \code{ignore_I = FALSE}, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. \cr
|
||||||
|
|
||||||
|
\strong{2. Using} \code{type = "points"} \strong{and parameter} \code{points_threshold} \cr
|
||||||
|
A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds \code{points_threshold}, an isolate will be (re)selected as a first weighted isolate.
|
||||||
|
}
|
||||||
|
|
||||||
\examples{
|
\examples{
|
||||||
# septic_patients is a dataset available in the AMR package
|
# septic_patients is a dataset available in the AMR package
|
||||||
?septic_patients
|
?septic_patients
|
||||||
@ -120,6 +125,9 @@ tbl$first_resp_isolate_weighed <-
|
|||||||
col_keyantibiotics = 'keyab')
|
col_keyantibiotics = 'keyab')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
\seealso{
|
||||||
|
\code{\link{keyantibiotics}}
|
||||||
|
}
|
||||||
\keyword{first}
|
\keyword{first}
|
||||||
\keyword{isolate}
|
\keyword{isolate}
|
||||||
\keyword{isolates}
|
\keyword{isolates}
|
||||||
|
@ -1,37 +1,76 @@
|
|||||||
% Generated by roxygen2: do not edit by hand
|
% Generated by roxygen2: do not edit by hand
|
||||||
% Please edit documentation in R/first_isolates.R
|
% Please edit documentation in R/key_antibiotics.R
|
||||||
\name{key_antibiotics}
|
\name{key_antibiotics}
|
||||||
\alias{key_antibiotics}
|
\alias{key_antibiotics}
|
||||||
\title{Key antibiotics based on bacteria ID}
|
\alias{key_antibiotics_equal}
|
||||||
|
\title{Key antibiotics for first \emph{weighted} isolates}
|
||||||
\usage{
|
\usage{
|
||||||
key_antibiotics(tbl, col_bactid = "bactid", info = TRUE, amcl = "amcl",
|
key_antibiotics(tbl, col_bactid = "bactid", amcl = "amcl", amox = "amox",
|
||||||
amox = "amox", cfot = "cfot", cfta = "cfta", cftr = "cftr",
|
cfot = "cfot", cfta = "cfta", cfur = "cfur", cipr = "cipr",
|
||||||
cfur = "cfur", cipr = "cipr", clar = "clar", clin = "clin",
|
coli = "coli", eryt = "eryt", gent = "gent", mero = "mero",
|
||||||
clox = "clox", doxy = "doxy", gent = "gent", line = "line",
|
oxac = "oxac", pita = "pita", rifa = "rifa", teic = "teic",
|
||||||
mero = "mero", peni = "peni", pita = "pita", rifa = "rifa",
|
tetr = "tetr", tobr = "tobr", trsu = "trsu", vanc = "vanc",
|
||||||
teic = "teic", trsu = "trsu", vanc = "vanc")
|
info = TRUE)
|
||||||
|
|
||||||
|
key_antibiotics_equal(x, y, type = c("keyantibiotics", "points"),
|
||||||
|
ignore_I = TRUE, points_threshold = 2, info = FALSE)
|
||||||
}
|
}
|
||||||
\arguments{
|
\arguments{
|
||||||
\item{tbl}{table with antibiotics coloms, like \code{amox} and \code{amcl}.}
|
\item{tbl}{table with antibiotics coloms, like \code{amox} and \code{amcl}.}
|
||||||
|
|
||||||
\item{col_bactid}{column name of the unique IDs of the microorganisms (should occur in the \code{\link{microorganisms}} dataset). Get your bactid's with the function \code{\link{guess_bactid}}, that takes microorganism names as input.}
|
\item{col_bactid}{column name of the unique IDs of the microorganisms (should occur in the \code{\link{microorganisms}} dataset). Get your bactid's with the function \code{\link{guess_bactid}}, that takes microorganism names as input.}
|
||||||
|
|
||||||
|
\item{amcl, amox, cfot, cfta, cfur, cipr, coli, eryt, gent, mero, oxac, pita, rifa, teic, tetr, tobr, trsu, vanc}{column names of antibiotics, case-insensitive}
|
||||||
|
|
||||||
\item{info}{print progress}
|
\item{info}{print progress}
|
||||||
|
|
||||||
\item{amcl, amox, cfot, cfta, cftr, cfur, cipr, clar, clin, clox, doxy, gent, line, mero, peni, pita, rifa, teic, trsu, vanc}{column names of antibiotics, case-insensitive}
|
\item{type}{type to determine weighed isolates; can be \code{"keyantibiotics"} or \code{"points"}, see Details}
|
||||||
}
|
|
||||||
\value{
|
\item{ignore_I}{logical to determine whether antibiotic interpretations with \code{"I"} will be ignored when \code{type = "keyantibiotics"}, see Details}
|
||||||
Character of length 1.
|
|
||||||
|
\item{points_threshold}{points until the comparison of key antibiotics will lead to inclusion of an isolate when \code{type = "points"}, see Details}
|
||||||
}
|
}
|
||||||
\description{
|
\description{
|
||||||
Key antibiotics based on bacteria ID
|
These function can be used to determine first isolates (see \code{\link{first_isolate}}). Using key antibiotics to determine first isolates is more reliable than without key antibiotics. These selected isolates will then be called first \emph{weighted} isolates.
|
||||||
}
|
}
|
||||||
|
\details{
|
||||||
|
The function \code{key_antibiotics} returns a character vector with antibiotic results.
|
||||||
|
|
||||||
|
The antibiotics that are used for \strong{Gram positive bacteria} are (colum names): \cr
|
||||||
|
amox, amcl, cfur, pita, cipr, trsu, vanc, teic, tetr, eryt, oxac, rifa.
|
||||||
|
|
||||||
|
The antibiotics that are used for \strong{Gram negative bacteria} are (colum names): \cr
|
||||||
|
amox, amcl, cfur, pita, cipr, trsu, gent, tobr, coli, cfot, cfta, mero.
|
||||||
|
|
||||||
|
|
||||||
|
The function \code{key_antibiotics_equal} checks the characters returned by \code{key_antibiotics} for equality, and returns a logical value.
|
||||||
|
}
|
||||||
|
\section{Key antibiotics}{
|
||||||
|
|
||||||
|
There are two ways to determine whether isolates can be included as first \emph{weighted} isolates: \cr
|
||||||
|
|
||||||
|
\strong{1. Using} \code{type = "keyantibiotics"} \strong{and parameter} \code{ignore_I} \cr
|
||||||
|
Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With \code{ignore_I = FALSE}, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. \cr
|
||||||
|
|
||||||
|
\strong{2. Using} \code{type = "points"} \strong{and parameter} \code{points_threshold} \cr
|
||||||
|
A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds \code{points_threshold}, an isolate will be (re)selected as a first weighted isolate.
|
||||||
|
}
|
||||||
|
|
||||||
\examples{
|
\examples{
|
||||||
\donttest{
|
\dontrun{
|
||||||
#' # set key antibiotics to a new variable
|
# set key antibiotics to a new variable
|
||||||
tbl$keyab <- key_antibiotics(tbl)
|
tbl$keyab <- key_antibiotics(tbl)
|
||||||
|
|
||||||
|
# add regular first isolates
|
||||||
|
tbl$first_isolate <-
|
||||||
|
first_isolate(tbl)
|
||||||
|
|
||||||
|
# add first WEIGHTED isolates using key antibiotics
|
||||||
|
tbl$first_isolate_weighed <-
|
||||||
|
first_isolate(tbl,
|
||||||
|
col_keyantibiotics = 'keyab')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
\seealso{
|
\seealso{
|
||||||
\code{\link{mo_property}} \code{\link{antibiotics}}
|
\code{\link{first_isolate}}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ test_that("first isolates work", {
|
|||||||
info = TRUE),
|
info = TRUE),
|
||||||
na.rm = TRUE)),
|
na.rm = TRUE)),
|
||||||
1963)
|
1963)
|
||||||
# and 1998 when using points
|
# and 1997 when using points
|
||||||
expect_equal(
|
expect_equal(
|
||||||
suppressWarnings(
|
suppressWarnings(
|
||||||
sum(
|
sum(
|
||||||
@ -44,7 +44,7 @@ test_that("first isolates work", {
|
|||||||
type = "points",
|
type = "points",
|
||||||
info = TRUE),
|
info = TRUE),
|
||||||
na.rm = TRUE)),
|
na.rm = TRUE)),
|
||||||
1998)
|
1997)
|
||||||
|
|
||||||
# septic_patients contains 1732 out of 2000 first non-ICU isolates
|
# septic_patients contains 1732 out of 2000 first non-ICU isolates
|
||||||
expect_equal(
|
expect_equal(
|
||||||
|
Loading…
Reference in New Issue
Block a user