2020-06-17 01:39:30 +02:00
# ==================================================================== #
2023-07-08 17:30:05 +02:00
# TITLE: #
2022-10-05 09:12:22 +02:00
# AMR: An R Package for Working with Antimicrobial Resistance Data #
2020-06-17 01:39:30 +02:00
# #
2023-07-08 17:30:05 +02:00
# SOURCE CODE: #
2020-07-08 14:48:06 +02:00
# https://github.com/msberends/AMR #
2020-06-17 01:39:30 +02:00
# #
2023-07-08 17:30:05 +02:00
# PLEASE CITE THIS SOFTWARE AS: #
2024-07-16 14:51:57 +02:00
# Berends MS, Luz CF, Friedrich AW, et al. (2022). #
# AMR: An R Package for Working with Antimicrobial Resistance Data. #
# Journal of Statistical Software, 104(3), 1-31. #
2023-05-27 10:39:22 +02:00
# https://doi.org/10.18637/jss.v104.i03 #
2022-10-05 09:12:22 +02:00
# #
2022-12-27 15:16:15 +01:00
# Developed at the University of Groningen and the University Medical #
# Center Groningen in The Netherlands, in collaboration with many #
# colleagues from around the world, see our website. #
2020-06-17 01:39:30 +02:00
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
# GNU General Public License version 2.0 (GNU GPL-2), as published by #
# the Free Software Foundation. #
# We created this package for both routine data analysis and academic #
# research and it was publicly released in the hope that it will be #
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
2020-10-08 11:16:03 +02:00
# #
# Visit our website for the full manual and a complete tutorial about #
2021-02-02 23:57:35 +01:00
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
2020-06-17 01:39:30 +02:00
# ==================================================================== #
2021-08-16 21:54:34 +02:00
#' Antibiotic Selectors
2022-08-28 10:31:50 +02:00
#'
2023-03-11 16:54:02 +01:00
#' @description These functions allow for filtering rows and selecting columns based on antibiotic test results that are of a specific antibiotic class or group (according to the [antibiotics] data set), without the need to define the columns or antibiotic abbreviations.
2023-03-12 13:02:37 +01:00
#'
2023-03-11 16:54:02 +01:00
#' In short, if you have a column name that resembles an antimicrobial drug, it will be picked up by any of these functions that matches its pharmaceutical class: "cefazolin", "kefzol", "CZO" and "J01DB04" will all be picked up by [cephalosporins()].
2021-08-19 23:43:02 +02:00
#' @param ab_class an antimicrobial class or a part of it, such as `"carba"` and `"carbapenems"`. The columns `group`, `atc_group1` and `atc_group2` of the [antibiotics] data set will be searched (case-insensitive) for this value.
2021-08-16 21:54:34 +02:00
#' @param filter an [expression] to be evaluated in the [antibiotics] data set, such as `name %like% "trim"`
2023-02-22 14:38:57 +01:00
#' @param only_sir_columns a [logical] to indicate whether only columns of class `sir` must be selected (default is `FALSE`), see [as.sir()]
#' @param only_treatable a [logical] to indicate whether antimicrobial drugs should be excluded that are only for laboratory tests (default is `TRUE`), such as gentamicin-high (`GEH`) and imipenem/EDTA (`IPE`)
2021-08-17 14:34:11 +02:00
#' @param ... ignored, only in place to allow future extensions
2021-06-22 12:16:42 +02:00
#' @details
2023-03-11 16:54:02 +01:00
#' These functions can be used in data set calls for selecting columns and filtering rows. They work with base \R, the Tidyverse, and `data.table`. They are heavily inspired by the [Tidyverse selection helpers][tidyselect::language] such as [`everything()`][tidyselect::everything()], but are not limited to `dplyr` verbs. Nonetheless, they are very convenient to use with `dplyr` functions such as [`select()`][dplyr::select()], [`filter()`][dplyr::filter()] and [`summarise()`][dplyr::summarise()], see *Examples*.
2022-08-28 10:31:50 +02:00
#'
#' All columns in the data in which these functions are called will be searched for known antibiotic names, abbreviations, brand names, and codes (ATC, EARS-Net, WHO, etc.) according to the [antibiotics] data set. This means that a selector such as [aminoglycosides()] will pick up column names like 'gen', 'genta', 'J01GB03', 'tobra', 'Tobracin', etc.
#'
2021-08-19 23:43:02 +02:00
#' The [ab_class()] function can be used to filter/select on a manually defined antibiotic class. It searches for results in the [antibiotics] data set within the columns `group`, `atc_group1` and `atc_group2`.
2021-08-16 21:54:34 +02:00
#' @section Full list of supported (antibiotic) classes:
2022-08-28 10:31:50 +02:00
#'
2021-08-16 21:54:34 +02:00
#' `r paste0(" * ", na.omit(sapply(DEFINED_AB_GROUPS, function(ab) ifelse(tolower(gsub("^AB_", "", ab)) %in% ls(envir = asNamespace("AMR")), paste0("[", tolower(gsub("^AB_", "", ab)), "()] can select: \\cr ", vector_and(paste0(ab_name(eval(parse(text = ab), envir = asNamespace("AMR")), language = NULL, tolower = TRUE), " (", eval(parse(text = ab), envir = asNamespace("AMR")), ")"), quotes = FALSE, sort = TRUE)), character(0)), USE.NAMES = FALSE)), "\n", collapse = "")`
2020-06-17 01:39:30 +02:00
#' @rdname antibiotic_class_selectors
#' @name antibiotic_class_selectors
2021-08-16 21:54:34 +02:00
#' @return (internally) a [character] vector of column names, with additional class `"ab_selector"`
2020-06-17 01:39:30 +02:00
#' @export
2021-01-18 16:57:56 +01:00
#' @inheritSection AMR Reference Data Publicly Available
2022-08-28 10:31:50 +02:00
#' @examples
2021-01-24 14:48:56 +01:00
#' # `example_isolates` is a data set available in the AMR package.
2020-12-27 20:32:40 +01:00
#' # See ?example_isolates.
2022-08-27 20:49:37 +02:00
#' example_isolates
2023-03-12 13:02:37 +01:00
#'
#'
2024-06-15 15:33:49 +02:00
#' # Examples sections below are split into 'dplyr', 'base R', and 'data.table':
#'
2021-05-24 09:00:11 +02:00
#' \donttest{
2023-03-11 16:54:02 +01:00
#' # dplyr -------------------------------------------------------------------
2024-06-15 15:33:49 +02:00
#'
#' if (require("dplyr")) {
2024-06-16 20:53:50 +02:00
#' example_isolates %>% select(carbapenems())
2024-06-15 15:33:49 +02:00
#' }
#'
#' if (require("dplyr")) {
#' # select columns 'mo', 'AMK', 'GEN', 'KAN' and 'TOB'
#' example_isolates %>% select(mo, aminoglycosides())
#' }
2023-03-12 13:02:37 +01:00
#'
2023-03-11 16:54:02 +01:00
#' if (require("dplyr")) {
2024-06-15 15:33:49 +02:00
#' # select only antibiotic columns with DDDs for oral treatment
2024-06-16 20:53:50 +02:00
#' example_isolates %>% select(administrable_per_os())
2023-03-11 16:54:02 +01:00
#' }
2023-03-12 13:02:37 +01:00
#'
2020-09-29 23:35:46 +02:00
#' if (require("dplyr")) {
2022-08-27 20:49:37 +02:00
#' # get AMR for all aminoglycosides e.g., per ward:
#' example_isolates %>%
2022-08-28 10:31:50 +02:00
#' group_by(ward) %>%
2024-06-15 15:33:49 +02:00
#' summarise(across(aminoglycosides(),
#' resistance))
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2021-08-16 21:54:34 +02:00
#' # You can combine selectors with '&' to be more specific:
2022-08-27 20:49:37 +02:00
#' example_isolates %>%
2021-08-16 21:54:34 +02:00
#' select(penicillins() & administrable_per_os())
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2021-12-09 10:48:25 +01:00
#' # get AMR for only drugs that matter - no intrinsic resistance:
2022-08-27 20:49:37 +02:00
#' example_isolates %>%
2022-08-28 10:31:50 +02:00
#' filter(mo_genus() %in% c("Escherichia", "Klebsiella")) %>%
#' group_by(ward) %>%
2024-06-15 15:33:49 +02:00
#' summarise_at(not_intrinsic_resistant(),
#' resistance)
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2021-08-16 21:54:34 +02:00
#' # get susceptibility for antibiotics whose name contains "trim":
2022-08-27 20:49:37 +02:00
#' example_isolates %>%
2022-08-28 10:31:50 +02:00
#' filter(first_isolate()) %>%
#' group_by(ward) %>%
2021-08-16 21:54:34 +02:00
#' summarise(across(ab_selector(name %like% "trim"), susceptibility))
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2020-06-17 01:39:30 +02:00
#' # this will select columns 'IPM' (imipenem) and 'MEM' (meropenem):
2022-08-28 10:31:50 +02:00
#' example_isolates %>%
2020-06-17 01:39:30 +02:00
#' select(carbapenems())
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2020-06-17 01:39:30 +02:00
#' # this will select columns 'mo', 'AMK', 'GEN', 'KAN' and 'TOB':
2022-08-28 10:31:50 +02:00
#' example_isolates %>%
2020-06-17 01:39:30 +02:00
#' select(mo, aminoglycosides())
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2022-08-28 10:31:50 +02:00
#' # any() and all() work in dplyr's filter() too:
#' example_isolates %>%
#' filter(
#' any(aminoglycosides() == "R"),
#' all(cephalosporins_2nd() == "R")
#' )
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2022-08-28 10:31:50 +02:00
#' # also works with c():
#' example_isolates %>%
2021-05-19 22:55:42 +02:00
#' filter(any(c(carbapenems(), aminoglycosides()) == "R"))
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2022-08-28 10:31:50 +02:00
#' # not setting any/all will automatically apply all():
#' example_isolates %>%
2021-05-19 22:55:42 +02:00
#' filter(aminoglycosides() == "R")
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2020-06-17 15:14:37 +02:00
#' # this will select columns 'mo' and all antimycobacterial drugs ('RIF'):
2022-08-28 10:31:50 +02:00
#' example_isolates %>%
2020-06-17 15:14:37 +02:00
#' select(mo, ab_class("mycobact"))
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2022-08-21 16:37:20 +02:00
#' # get bug/drug combinations for only glycopeptides in Gram-positives:
2022-08-28 10:31:50 +02:00
#' example_isolates %>%
#' filter(mo_is_gram_positive()) %>%
#' select(mo, glycopeptides()) %>%
2020-06-17 15:14:37 +02:00
#' bug_drug_combinations() %>%
#' format()
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2022-08-28 10:31:50 +02:00
#' data.frame(
#' some_column = "some_value",
#' J01CA01 = "S"
#' ) %>% # ATC code of ampicillin
#' select(penicillins()) # only the 'J01CA01' column will be selected
2022-08-27 20:49:37 +02:00
#' }
#' if (require("dplyr")) {
2023-03-12 13:02:37 +01:00
#' # with recent versions of dplyr, this is all equal:
2022-08-27 20:49:37 +02:00
#' x <- example_isolates[carbapenems() == "R", ]
#' y <- example_isolates %>% filter(carbapenems() == "R")
2022-08-28 10:31:50 +02:00
#' z <- example_isolates %>% filter(if_all(carbapenems(), ~ .x == "R"))
2022-08-27 20:49:37 +02:00
#' identical(x, y) && identical(y, z)
2020-06-17 01:39:30 +02:00
#' }
2023-03-12 13:02:37 +01:00
#'
#'
2024-06-15 15:33:49 +02:00
#' # base R ------------------------------------------------------------------
#'
#' # select columns 'IPM' (imipenem) and 'MEM' (meropenem)
#' example_isolates[, carbapenems()]
#'
#' # select columns 'mo', 'AMK', 'GEN', 'KAN' and 'TOB'
#' example_isolates[, c("mo", aminoglycosides())]
#'
#' # select only antibiotic columns with DDDs for oral treatment
#' example_isolates[, administrable_per_os()]
#'
#' # filter using any() or all()
#' example_isolates[any(carbapenems() == "R"), ]
#' subset(example_isolates, any(carbapenems() == "R"))
#'
#' # filter on any or all results in the carbapenem columns (i.e., IPM, MEM):
#' example_isolates[any(carbapenems()), ]
#' example_isolates[all(carbapenems()), ]
#'
#' # filter with multiple antibiotic selectors using c()
#' example_isolates[all(c(carbapenems(), aminoglycosides()) == "R"), ]
#'
#' # filter + select in one go: get penicillins in carbapenem-resistant strains
#' example_isolates[any(carbapenems() == "R"), penicillins()]
#'
#' # You can combine selectors with '&' to be more specific. For example,
#' # penicillins() would select benzylpenicillin ('peni G') and
#' # administrable_per_os() would select erythromycin. Yet, when combined these
#' # drugs are both omitted since benzylpenicillin is not administrable per os
#' # and erythromycin is not a penicillin:
#' example_isolates[, penicillins() & administrable_per_os()]
#'
#' # ab_selector() applies a filter in the `antibiotics` data set and is thus
#' # very flexible. For instance, to select antibiotic columns with an oral DDD
#' # of at least 1 gram:
#' example_isolates[, ab_selector(oral_ddd > 1 & oral_units == "g")]
#'
#'
2023-03-11 16:54:02 +01:00
#' # data.table --------------------------------------------------------------
2023-03-12 13:02:37 +01:00
#'
2023-03-11 16:54:02 +01:00
#' # data.table is supported as well, just use it in the same way as with
2023-03-12 13:02:37 +01:00
#' # base R, but add `with = FALSE` if using a single AB selector.
#'
2023-03-11 16:54:02 +01:00
#' if (require("data.table")) {
#' dt <- as.data.table(example_isolates)
2023-03-12 13:02:37 +01:00
#'
#' # this does not work, it returns column *names*
#' dt[, carbapenems()]
#' }
#' if (require("data.table")) {
#' # so `with = FALSE` is required
#' dt[, carbapenems(), with = FALSE]
#' }
#'
#' # for multiple selections or AB selectors, `with = FALSE` is not needed:
#' if (require("data.table")) {
#' dt[, c("mo", aminoglycosides())]
#' }
#' if (require("data.table")) {
#' dt[, c(carbapenems(), aminoglycosides())]
#' }
#'
#' # row filters are also supported:
#' if (require("data.table")) {
#' dt[any(carbapenems() == "S"), ]
#' }
#' if (require("data.table")) {
#' dt[any(carbapenems() == "S"), penicillins(), with = FALSE]
2023-03-11 16:54:02 +01:00
#' }
2021-05-24 09:00:11 +02:00
#' }
2022-08-28 10:31:50 +02:00
ab_class <- function ( ab_class ,
2023-01-21 23:47:20 +01:00
only_sir_columns = FALSE ,
2021-08-17 14:34:11 +02:00
only_treatable = TRUE ,
... ) {
2021-07-04 22:10:46 +02:00
meet_criteria ( ab_class , allow_class = " character" , has_length = 1 , allow_NULL = TRUE )
2023-01-21 23:47:20 +01:00
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2021-07-08 22:23:28 +02:00
meet_criteria ( only_treatable , allow_class = " logical" , has_length = 1 )
2023-01-21 23:47:20 +01:00
ab_select_exec ( NULL , only_sir_columns = only_sir_columns , ab_class_args = ab_class , only_treatable = only_treatable )
2021-08-16 21:54:34 +02:00
}
#' @rdname antibiotic_class_selectors
2021-12-09 10:48:25 +01:00
#' @details The [ab_selector()] function can be used to internally filter the [antibiotics] data set on any results, see *Examples*. It allows for filtering on a (part of) a certain name, and/or a group name or even a minimum of DDDs for oral treatment. This function yields the highest flexibility, but is also the least user-friendly, since it requires a hard-coded filter to set.
2021-08-16 21:54:34 +02:00
#' @export
2022-08-28 10:31:50 +02:00
ab_selector <- function ( filter ,
2023-01-21 23:47:20 +01:00
only_sir_columns = FALSE ,
2021-08-17 14:34:11 +02:00
only_treatable = TRUE ,
... ) {
2023-01-21 23:47:20 +01:00
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2021-08-16 21:54:34 +02:00
meet_criteria ( only_treatable , allow_class = " logical" , has_length = 1 )
2022-08-28 10:31:50 +02:00
2021-08-16 21:54:34 +02:00
# get_current_data() has to run each time, for cases where e.g., filter() and select() are used in same call
# but it only takes a couple of milliseconds
vars_df <- get_current_data ( arg_name = NA , call = -2 )
# to improve speed, get_column_abx() will only run once when e.g. in a select or group call
2022-08-28 10:31:50 +02:00
ab_in_data <- get_column_abx ( vars_df ,
2023-01-21 23:47:20 +01:00
info = FALSE , only_sir_columns = only_sir_columns ,
2022-08-28 10:31:50 +02:00
sort = FALSE , fn = " ab_selector"
)
2021-08-16 21:54:34 +02:00
call <- substitute ( filter )
2022-10-14 13:02:50 +02:00
agents <- tryCatch ( AMR_env $ AB_lookup [which ( eval ( call , envir = AMR_env $ AB_lookup ) ) , " ab" , drop = TRUE ] ,
2022-08-28 10:31:50 +02:00
error = function ( e ) stop_ ( e $ message , call = -5 )
)
2021-08-16 21:54:34 +02:00
agents <- ab_in_data [ab_in_data %in% agents ]
2022-08-28 10:31:50 +02:00
message_agent_names (
function_name = " ab_selector" ,
agents = agents ,
ab_group = NULL ,
examples = " " ,
call = call
)
2021-08-16 21:54:34 +02:00
structure ( unname ( agents ) ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector" , " character" )
)
2021-08-16 21:54:34 +02:00
}
2020-06-17 15:14:37 +02:00
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
aminoglycosides <- function ( only_sir_columns = FALSE , only_treatable = TRUE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2021-07-08 22:23:28 +02:00
meet_criteria ( only_treatable , allow_class = " logical" , has_length = 1 )
2023-01-21 23:47:20 +01:00
ab_select_exec ( " aminoglycosides" , only_sir_columns = only_sir_columns , only_treatable = only_treatable )
2021-06-04 21:07:55 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
aminopenicillins <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " aminopenicillins" , only_sir_columns = only_sir_columns )
2021-08-16 21:54:34 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
antifungals <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " antifungals" , only_sir_columns = only_sir_columns )
2021-08-16 21:54:34 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
antimycobacterials <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " antimycobacterials" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
2021-05-18 00:53:04 +02:00
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
betalactams <- function ( only_sir_columns = FALSE , only_treatable = TRUE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2021-07-08 22:23:28 +02:00
meet_criteria ( only_treatable , allow_class = " logical" , has_length = 1 )
2023-01-21 23:47:20 +01:00
ab_select_exec ( " betalactams" , only_sir_columns = only_sir_columns , only_treatable = only_treatable )
2021-05-18 00:53:04 +02:00
}
2021-06-04 21:07:55 +02:00
2020-06-17 01:39:30 +02:00
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
carbapenems <- function ( only_sir_columns = FALSE , only_treatable = TRUE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2021-07-08 22:23:28 +02:00
meet_criteria ( only_treatable , allow_class = " logical" , has_length = 1 )
2023-01-21 23:47:20 +01:00
ab_select_exec ( " carbapenems" , only_sir_columns = only_sir_columns , only_treatable = only_treatable )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
cephalosporins <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " cephalosporins" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
cephalosporins_1st <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " cephalosporins_1st" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
cephalosporins_2nd <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " cephalosporins_2nd" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
cephalosporins_3rd <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " cephalosporins_3rd" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
cephalosporins_4th <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " cephalosporins_4th" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
cephalosporins_5th <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " cephalosporins_5th" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
fluoroquinolones <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " fluoroquinolones" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
glycopeptides <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " glycopeptides" , only_sir_columns = only_sir_columns )
2021-06-04 21:07:55 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2024-06-08 17:35:25 +02:00
lincosamides <- function ( only_sir_columns = FALSE , only_treatable = TRUE , ... ) {
2023-01-21 23:47:20 +01:00
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2024-06-08 17:35:25 +02:00
meet_criteria ( only_treatable , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " lincosamides" , only_sir_columns = only_sir_columns , only_treatable = only_treatable )
2021-06-04 21:07:55 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
lipoglycopeptides <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " lipoglycopeptides" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
macrolides <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " macrolides" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
2024-06-08 17:35:25 +02:00
#' @rdname antibiotic_class_selectors
#' @export
nitrofurans <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " nitrofurans" , only_sir_columns = only_sir_columns )
}
2020-06-17 01:39:30 +02:00
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
oxazolidinones <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " oxazolidinones" , only_sir_columns = only_sir_columns )
2021-02-08 14:18:42 +01:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
penicillins <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " penicillins" , only_sir_columns = only_sir_columns )
2021-06-04 21:07:55 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
polymyxins <- function ( only_sir_columns = FALSE , only_treatable = TRUE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2021-07-08 22:23:28 +02:00
meet_criteria ( only_treatable , allow_class = " logical" , has_length = 1 )
2023-01-21 23:47:20 +01:00
ab_select_exec ( " polymyxins" , only_sir_columns = only_sir_columns , only_treatable = only_treatable )
2021-06-04 21:07:55 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2024-06-08 17:35:25 +02:00
quinolones <- function ( only_sir_columns = FALSE , ... ) {
2023-01-21 23:47:20 +01:00
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2024-06-08 17:35:25 +02:00
ab_select_exec ( " quinolones" , only_sir_columns = only_sir_columns )
2021-06-04 21:07:55 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2024-06-08 17:35:25 +02:00
rifamycins <- function ( only_sir_columns = FALSE , ... ) {
2023-01-21 23:47:20 +01:00
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2024-06-08 17:35:25 +02:00
ab_select_exec ( " rifamycins" , only_sir_columns = only_sir_columns )
}
#' @rdname antibiotic_class_selectors
#' @export
streptogramins <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " streptogramins" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
tetracyclines <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " tetracyclines" , only_sir_columns = only_sir_columns )
2021-08-16 21:54:34 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
trimethoprims <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " trimethoprims" , only_sir_columns = only_sir_columns )
2021-06-04 21:07:55 +02:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
ureidopenicillins <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
ab_select_exec ( " ureidopenicillins" , only_sir_columns = only_sir_columns )
2020-06-17 01:39:30 +02:00
}
2021-12-09 10:48:25 +01:00
#' @rdname antibiotic_class_selectors
#' @details The [administrable_per_os()] and [administrable_iv()] functions also rely on the [antibiotics] data set - antibiotic columns will be matched where a DDD (defined daily dose) for resp. oral and IV treatment is available in the [antibiotics] data set.
#' @export
2023-01-21 23:47:20 +01:00
administrable_per_os <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2021-12-09 10:48:25 +01:00
# get_current_data() has to run each time, for cases where e.g., filter() and select() are used in same call
# but it only takes a couple of milliseconds
vars_df <- get_current_data ( arg_name = NA , call = -2 )
# to improve speed, get_column_abx() will only run once when e.g. in a select or group call
2022-08-28 10:31:50 +02:00
ab_in_data <- get_column_abx ( vars_df ,
2023-01-21 23:47:20 +01:00
info = FALSE , only_sir_columns = only_sir_columns ,
2022-08-28 10:31:50 +02:00
sort = FALSE , fn = " administrable_per_os"
)
2022-10-14 13:02:50 +02:00
agents_all <- AMR_env $ AB_lookup [which ( ! is.na ( AMR_env $ AB_lookup $ oral_ddd ) ) , " ab" , drop = TRUE ]
agents <- AMR_env $ AB_lookup [which ( AMR_env $ AB_lookup $ ab %in% ab_in_data & ! is.na ( AMR_env $ AB_lookup $ oral_ddd ) ) , " ab" , drop = TRUE ]
2021-12-09 10:48:25 +01:00
agents <- ab_in_data [ab_in_data %in% agents ]
2022-08-28 10:31:50 +02:00
message_agent_names (
function_name = " administrable_per_os" ,
agents = agents ,
ab_group = " administrable_per_os" ,
examples = paste0 (
" (such as " ,
2023-01-23 15:01:21 +01:00
vector_or (
ab_name (
sample ( agents_all ,
size = min ( 5 , length ( agents_all ) ) ,
replace = FALSE
) ,
tolower = TRUE ,
language = NULL
) ,
quotes = FALSE
2022-08-28 10:31:50 +02:00
) ,
" )"
)
)
2021-12-09 10:48:25 +01:00
structure ( unname ( agents ) ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector" , " character" )
)
2021-12-09 10:48:25 +01:00
}
#' @rdname antibiotic_class_selectors
#' @export
2023-01-21 23:47:20 +01:00
administrable_iv <- function ( only_sir_columns = FALSE , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2021-12-09 10:48:25 +01:00
# get_current_data() has to run each time, for cases where e.g., filter() and select() are used in same call
# but it only takes a couple of milliseconds
vars_df <- get_current_data ( arg_name = NA , call = -2 )
# to improve speed, get_column_abx() will only run once when e.g. in a select or group call
2022-08-28 10:31:50 +02:00
ab_in_data <- get_column_abx ( vars_df ,
2023-01-21 23:47:20 +01:00
info = FALSE , only_sir_columns = only_sir_columns ,
2022-08-28 10:31:50 +02:00
sort = FALSE , fn = " administrable_iv"
)
2022-10-14 13:02:50 +02:00
agents_all <- AMR_env $ AB_lookup [which ( ! is.na ( AMR_env $ AB_lookup $ iv_ddd ) ) , " ab" , drop = TRUE ]
agents <- AMR_env $ AB_lookup [which ( AMR_env $ AB_lookup $ ab %in% ab_in_data & ! is.na ( AMR_env $ AB_lookup $ iv_ddd ) ) , " ab" , drop = TRUE ]
2021-12-09 10:48:25 +01:00
agents <- ab_in_data [ab_in_data %in% agents ]
2022-08-28 10:31:50 +02:00
message_agent_names (
function_name = " administrable_iv" ,
agents = agents ,
ab_group = " administrable_iv" ,
examples = " "
)
2021-12-09 10:48:25 +01:00
structure ( unname ( agents ) ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector" , " character" )
)
2021-12-09 10:48:25 +01:00
}
#' @rdname antibiotic_class_selectors
#' @inheritParams eucast_rules
2023-06-22 15:10:59 +02:00
#' @details The [not_intrinsic_resistant()] function can be used to only select antibiotic columns that pose no intrinsic resistance for the microorganisms in the data set. For example, if a data set contains only microorganism codes or names of *E. coli* and *K. pneumoniae* and contains a column "vancomycin", this column will be removed (or rather, unselected) using this function. It currently applies `r format_eucast_version_nr(names(EUCAST_VERSION_EXPERT_RULES[1]))` to determine intrinsic resistance, using the [eucast_rules()] function internally. Because of this determination, this function is quite slow in terms of performance.
2021-12-09 10:48:25 +01:00
#' @export
2023-01-21 23:47:20 +01:00
not_intrinsic_resistant <- function ( only_sir_columns = FALSE , col_mo = NULL , version_expertrules = 3.3 , ... ) {
meet_criteria ( only_sir_columns , allow_class = " logical" , has_length = 1 )
2021-12-09 10:48:25 +01:00
# get_current_data() has to run each time, for cases where e.g., filter() and select() are used in same call
# but it only takes a couple of milliseconds
vars_df <- get_current_data ( arg_name = NA , call = -2 )
# to improve speed, get_column_abx() will only run once when e.g. in a select or group call
2022-08-28 10:31:50 +02:00
ab_in_data <- get_column_abx ( vars_df ,
2023-01-21 23:47:20 +01:00
info = FALSE , only_sir_columns = only_sir_columns ,
2022-08-28 10:31:50 +02:00
sort = FALSE , fn = " not_intrinsic_resistant"
)
2021-12-09 10:48:25 +01:00
# intrinsic vars
2023-01-23 15:01:21 +01:00
vars_df_R <- tryCatch (
sapply (
eucast_rules ( vars_df ,
col_mo = col_mo ,
version_expertrules = version_expertrules ,
rules = " expert" ,
info = FALSE
) ,
function ( col ) {
tryCatch ( ! any ( is.na ( col ) ) && all ( col == " R" ) ,
error = function ( e ) FALSE
)
}
2022-08-28 10:31:50 +02:00
) ,
2023-01-23 15:01:21 +01:00
error = function ( e ) stop_ ( " in not_intrinsic_resistant(): " , e $ message , call = FALSE )
2022-08-28 10:31:50 +02:00
)
2024-02-24 15:16:52 +01:00
2021-12-09 10:48:25 +01:00
agents <- ab_in_data [ab_in_data %in% names ( vars_df_R [which ( vars_df_R ) ] ) ]
if ( length ( agents ) > 0 &&
2024-02-24 15:16:52 +01:00
message_not_thrown_before ( " not_intrinsic_resistant" , sort ( agents ) ) ) {
2021-12-09 10:48:25 +01:00
agents_formatted <- paste0 ( " '" , font_bold ( agents , collapse = NULL ) , " '" )
agents_names <- ab_name ( names ( agents ) , tolower = TRUE , language = NULL )
need_name <- generalise_antibiotic_name ( agents ) != generalise_antibiotic_name ( agents_names )
agents_formatted [need_name ] <- paste0 ( agents_formatted [need_name ] , " (" , agents_names [need_name ] , " )" )
2022-08-28 10:31:50 +02:00
message_ (
" For `not_intrinsic_resistant()` removing " ,
ifelse ( length ( agents ) == 1 , " column " , " columns " ) ,
vector_and ( agents_formatted , quotes = FALSE , sort = FALSE )
)
2021-12-09 10:48:25 +01:00
}
2024-02-24 15:16:52 +01:00
2021-12-09 10:48:25 +01:00
vars_df_R <- names ( vars_df_R ) [which ( ! vars_df_R ) ]
# find columns that are abx, but also intrinsic R
out <- unname ( intersect ( ab_in_data , vars_df_R ) )
structure ( out ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector" , " character" )
)
2021-12-09 10:48:25 +01:00
}
2021-08-16 21:54:34 +02:00
ab_select_exec <- function ( function_name ,
2023-01-21 23:47:20 +01:00
only_sir_columns = FALSE ,
2021-08-16 21:54:34 +02:00
only_treatable = FALSE ,
2021-08-19 23:43:02 +02:00
ab_class_args = NULL ) {
2021-06-04 21:07:55 +02:00
# get_current_data() has to run each time, for cases where e.g., filter() and select() are used in same call
2021-07-04 12:00:41 +02:00
# but it only takes a couple of milliseconds
2021-06-22 12:16:42 +02:00
vars_df <- get_current_data ( arg_name = NA , call = -3 )
2021-06-04 21:07:55 +02:00
# to improve speed, get_column_abx() will only run once when e.g. in a select or group call
2022-08-28 10:31:50 +02:00
ab_in_data <- get_column_abx ( vars_df ,
2023-01-21 23:47:20 +01:00
info = FALSE , only_sir_columns = only_sir_columns ,
2022-08-28 10:31:50 +02:00
sort = FALSE , fn = function_name
)
2022-10-30 14:31:45 +01:00
2021-07-08 22:23:28 +02:00
# untreatable drugs
2021-12-11 13:41:31 +01:00
if ( only_treatable == TRUE ) {
2024-06-08 17:35:25 +02:00
untreatable <- AMR_env $ AB_lookup [which ( AMR_env $ AB_lookup $ name %like% " -high|EDTA|polysorbate|macromethod|screening|nacubactam" ) , " ab" , drop = TRUE ]
2021-12-11 13:41:31 +01:00
if ( any ( untreatable %in% names ( ab_in_data ) ) ) {
2024-06-08 17:35:25 +02:00
if ( message_not_thrown_before ( function_name , " ab_class" , " untreatable" ) ) {
2022-08-28 10:31:50 +02:00
warning_ (
2022-11-13 13:44:25 +01:00
" in `" , function_name , " ()`: some drugs were ignored since they cannot be used for treating patients: " ,
2023-01-23 15:01:21 +01:00
vector_and (
ab_name ( names ( ab_in_data ) [names ( ab_in_data ) %in% untreatable ] ,
language = NULL ,
tolower = TRUE
) ,
quotes = FALSE ,
sort = TRUE
2024-06-08 17:35:25 +02:00
) , " . They can be included using `" , function_name , " (only_treatable = FALSE)`."
2022-08-28 10:31:50 +02:00
)
2021-12-11 13:41:31 +01:00
}
ab_in_data <- ab_in_data [ ! names ( ab_in_data ) %in% untreatable ]
2021-07-08 22:23:28 +02:00
}
}
2022-08-28 10:31:50 +02:00
2020-06-17 01:39:30 +02:00
if ( length ( ab_in_data ) == 0 ) {
2022-11-13 13:44:25 +01:00
message_ ( " No antimicrobial drugs found in the data." )
2020-06-17 01:39:30 +02:00
return ( NULL )
}
2022-08-28 10:31:50 +02:00
2022-10-05 09:12:22 +02:00
if ( is.null ( ab_class_args ) || isTRUE ( function_name %in% c ( " antifungals" , " antimycobacterials" ) ) ) {
ab_group <- NULL
if ( isTRUE ( function_name == " antifungals" ) ) {
2022-10-14 13:02:50 +02:00
abx <- AMR_env $ AB_lookup $ ab [which ( AMR_env $ AB_lookup $ group == " Antifungals" ) ]
2022-10-05 09:12:22 +02:00
} else if ( isTRUE ( function_name == " antimycobacterials" ) ) {
2022-10-14 13:02:50 +02:00
abx <- AMR_env $ AB_lookup $ ab [which ( AMR_env $ AB_lookup $ group == " Antimycobacterials" ) ]
2022-10-05 09:12:22 +02:00
} else {
2024-04-23 10:55:48 +02:00
# their upper case equivalent are vectors with class 'ab', created in data-raw/_pre_commit_checks.R
2022-10-05 09:12:22 +02:00
# carbapenems() gets its codes from AMR:::AB_CARBAPENEMS
abx <- get ( paste0 ( " AB_" , toupper ( function_name ) ) , envir = asNamespace ( " AMR" ) )
2022-10-11 10:49:55 +02:00
# manually added codes from add_custom_antimicrobials() must also be supported
if ( length ( AMR_env $ custom_ab_codes ) > 0 ) {
2022-10-14 13:02:50 +02:00
custom_ab <- AMR_env $ AB_lookup [which ( AMR_env $ AB_lookup $ ab %in% AMR_env $ custom_ab_codes ) , ]
2022-10-11 10:49:55 +02:00
check_string <- paste0 ( custom_ab $ group , custom_ab $ atc_group1 , custom_ab $ atc_group2 )
if ( function_name == " betalactams" ) {
find_group <- " beta-lactams"
} else if ( function_name %like% " cephalosporins_" ) {
find_group <- gsub ( " _(.*)$" , paste0 ( " (\\1 gen.)" ) , function_name )
} else {
find_group <- function_name
}
abx <- c ( abx , custom_ab $ ab [which ( check_string %like% find_group ) ] )
}
2022-10-05 09:12:22 +02:00
ab_group <- function_name
}
2023-01-23 15:01:21 +01:00
examples <- paste0 ( " (such as " , vector_or (
ab_name ( sample ( abx , size = min ( 2 , length ( abx ) ) , replace = FALSE ) ,
tolower = TRUE ,
language = NULL
) ,
quotes = FALSE
2022-08-28 10:31:50 +02:00
) , " )" )
2020-06-17 15:14:37 +02:00
} else {
2021-06-04 21:07:55 +02:00
# this for the 'manual' ab_class() function
2022-08-28 10:31:50 +02:00
abx <- subset (
2022-10-14 13:02:50 +02:00
AMR_env $ AB_lookup ,
2022-08-28 10:31:50 +02:00
group %like% ab_class_args |
atc_group1 %like% ab_class_args |
atc_group2 %like% ab_class_args
) $ ab
2021-08-19 23:43:02 +02:00
ab_group <- find_ab_group ( ab_class_args )
2021-06-04 21:07:55 +02:00
function_name <- " ab_class"
2021-08-19 23:43:02 +02:00
examples <- paste0 ( " (such as " , find_ab_names ( ab_class_args , 2 ) , " )" )
2020-06-17 15:14:37 +02:00
}
2022-08-28 10:31:50 +02:00
2020-06-17 01:39:30 +02:00
# get the columns with a group names in the chosen ab class
2021-06-04 21:07:55 +02:00
agents <- ab_in_data [names ( ab_in_data ) %in% abx ]
2022-08-28 10:31:50 +02:00
message_agent_names (
function_name = function_name ,
agents = agents ,
ab_group = ab_group ,
examples = examples ,
ab_class_args = ab_class_args
)
2021-07-23 21:42:11 +02:00
structure ( unname ( agents ) ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector" , " character" )
)
2021-05-19 22:55:42 +02:00
}
2024-06-15 15:33:49 +02:00
#' @method print ab_selector
#' @export
#' @noRd
print.ab_selector <- function ( x , ... ) {
warning_ ( " It should never be needed to print an antibiotic selector class. Are you using data.table? Then add the argument `with = FALSE`, see our examples at `?ab_selector`." ,
immediate = TRUE )
cat ( " Class 'ab_selector'\n" )
print ( as.character ( x ) , quote = FALSE )
}
2021-05-19 22:55:42 +02:00
#' @method c ab_selector
#' @export
#' @noRd
c.ab_selector <- function ( ... ) {
structure ( unlist ( lapply ( list ( ... ) , as.character ) ) ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector" , " character" )
)
2021-05-19 22:55:42 +02:00
}
all_any_ab_selector <- function ( type , ... , na.rm = TRUE ) {
cols_ab <- c ( ... )
2024-06-14 22:39:01 +02:00
result <- cols_ab [toupper ( cols_ab ) %in% c ( " S" , " SDD" , " I" , " R" , " NI" ) ]
2021-05-19 22:55:42 +02:00
if ( length ( result ) == 0 ) {
2023-01-21 23:47:20 +01:00
message_ ( " Filtering " , type , " of columns " , vector_and ( font_bold ( cols_ab , collapse = NULL ) , quotes = " '" ) , ' to contain value "S", "I" or "R"' )
2024-06-14 22:39:01 +02:00
result <- c ( " S" , " SDD" , " I" , " R" , " NI" )
2021-05-19 22:55:42 +02:00
}
cols_ab <- cols_ab [ ! cols_ab %in% result ]
df <- get_current_data ( arg_name = NA , call = -3 )
2022-08-28 10:31:50 +02:00
2021-05-19 22:55:42 +02:00
if ( type == " all" ) {
scope_fn <- all
} else {
scope_fn <- any
}
2022-08-28 10:31:50 +02:00
2021-05-19 22:55:42 +02:00
x_transposed <- as.list ( as.data.frame ( t ( df [ , cols_ab , drop = FALSE ] ) , stringsAsFactors = FALSE ) )
2022-08-28 10:31:50 +02:00
vapply (
FUN.VALUE = logical ( 1 ) ,
X = x_transposed ,
FUN = function ( y ) scope_fn ( y %in% result , na.rm = na.rm ) ,
USE.NAMES = FALSE
)
2021-05-19 22:55:42 +02:00
}
#' @method all ab_selector
#' @export
#' @noRd
all.ab_selector <- function ( ... , na.rm = FALSE ) {
all_any_ab_selector ( " all" , ... , na.rm = na.rm )
}
#' @method any ab_selector
#' @export
#' @noRd
any.ab_selector <- function ( ... , na.rm = FALSE ) {
all_any_ab_selector ( " any" , ... , na.rm = na.rm )
}
#' @method all ab_selector_any_all
#' @export
#' @noRd
all.ab_selector_any_all <- function ( ... , na.rm = FALSE ) {
# this is all() on a logical vector from `==.ab_selector` or `!=.ab_selector`
# e.g., example_isolates %>% filter(all(carbapenems() == "R"))
# so just return the vector as is, only correcting for na.rm
out <- unclass ( c ( ... ) )
2022-11-14 15:20:39 +01:00
if ( isTRUE ( na.rm ) ) {
2021-05-19 22:55:42 +02:00
out <- out [ ! is.na ( out ) ]
}
out
}
#' @method any ab_selector_any_all
#' @export
#' @noRd
any.ab_selector_any_all <- function ( ... , na.rm = FALSE ) {
# this is any() on a logical vector from `==.ab_selector` or `!=.ab_selector`
# e.g., example_isolates %>% filter(any(carbapenems() == "R"))
# so just return the vector as is, only correcting for na.rm
out <- unclass ( c ( ... ) )
2022-11-14 15:20:39 +01:00
if ( isTRUE ( na.rm ) ) {
2021-05-19 22:55:42 +02:00
out <- out [ ! is.na ( out ) ]
}
out
}
#' @method == ab_selector
#' @export
#' @noRd
`==.ab_selector` <- function ( e1 , e2 ) {
calls <- as.character ( match.call ( ) )
fn_name <- calls [2 ]
fn_name <- gsub ( " ^(c\\()(.*)(\\))$" , " \\2" , fn_name )
if ( is_any ( fn_name ) ) {
type <- " any"
} else if ( is_all ( fn_name ) ) {
type <- " all"
} else {
type <- " all"
if ( length ( e1 ) > 1 ) {
2022-08-28 10:31:50 +02:00
message_ (
" Assuming a filter on " , type , " " , length ( e1 ) , " " , gsub ( " [\\(\\)]" , " " , fn_name ) ,
" . Wrap around `all()` or `any()` to prevent this note."
)
2021-05-19 22:55:42 +02:00
}
}
structure ( all_any_ab_selector ( type = type , e1 , e2 ) ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector_any_all" , " logical" )
)
2021-05-19 22:55:42 +02:00
}
#' @method != ab_selector
#' @export
#' @noRd
`!=.ab_selector` <- function ( e1 , e2 ) {
calls <- as.character ( match.call ( ) )
fn_name <- calls [2 ]
fn_name <- gsub ( " ^(c\\()(.*)(\\))$" , " \\2" , fn_name )
if ( is_any ( fn_name ) ) {
type <- " any"
} else if ( is_all ( fn_name ) ) {
type <- " all"
} else {
type <- " all"
if ( length ( e1 ) > 1 ) {
2022-08-28 10:31:50 +02:00
message_ (
" Assuming a filter on " , type , " " , length ( e1 ) , " " , gsub ( " [\\(\\)]" , " " , fn_name ) ,
" . Wrap around `all()` or `any()` to prevent this note."
)
2021-05-19 22:55:42 +02:00
}
}
# this is `!=`, so turn around the values
2024-06-14 22:39:01 +02:00
sir <- c ( " S" , " SDD" , " I" , " R" , " NI" )
2023-01-21 23:47:20 +01:00
e2 <- sir [sir != e2 ]
2021-05-19 22:55:42 +02:00
structure ( all_any_ab_selector ( type = type , e1 , e2 ) ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector_any_all" , " logical" )
)
2021-05-19 22:55:42 +02:00
}
2021-08-16 21:54:34 +02:00
#' @method & ab_selector
#' @export
#' @noRd
`&.ab_selector` <- function ( e1 , e2 ) {
# this is only required for base R, since tidyselect has already implemented this
# e.g., for: example_isolates[, penicillins() & administrable_per_os()]
structure ( intersect ( unclass ( e1 ) , unclass ( e2 ) ) ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector" , " character" )
)
2021-08-16 21:54:34 +02:00
}
#' @method | ab_selector
#' @export
#' @noRd
`|.ab_selector` <- function ( e1 , e2 ) {
# this is only required for base R, since tidyselect has already implemented this
# e.g., for: example_isolates[, penicillins() | administrable_per_os()]
structure ( union ( unclass ( e1 ) , unclass ( e2 ) ) ,
2022-08-28 10:31:50 +02:00
class = c ( " ab_selector" , " character" )
)
2021-08-16 21:54:34 +02:00
}
2021-05-19 22:55:42 +02:00
is_any <- function ( el1 ) {
2022-10-05 09:12:22 +02:00
syscalls <- paste0 ( trimws2 ( deparse ( sys.calls ( ) ) ) , collapse = " " )
2021-05-19 22:55:42 +02:00
el1 <- gsub ( " (.*),.*" , " \\1" , el1 )
2021-12-11 13:41:31 +01:00
syscalls %like% paste0 ( " [^_a-zA-Z0-9]any\\(" , " (c\\()?" , el1 )
2021-05-19 22:55:42 +02:00
}
is_all <- function ( el1 ) {
2022-10-05 09:12:22 +02:00
syscalls <- paste0 ( trimws2 ( deparse ( sys.calls ( ) ) ) , collapse = " " )
2021-05-19 22:55:42 +02:00
el1 <- gsub ( " (.*),.*" , " \\1" , el1 )
2021-12-11 13:41:31 +01:00
syscalls %like% paste0 ( " [^_a-zA-Z0-9]all\\(" , " (c\\()?" , el1 )
2021-05-19 22:55:42 +02:00
}
2021-08-19 23:43:02 +02:00
find_ab_group <- function ( ab_class_args ) {
ab_class_args <- gsub ( " [^a-zA-Z0-9]" , " .*" , ab_class_args )
2023-02-09 13:07:39 +01:00
AMR_env $ AB_lookup %pm>%
subset ( group %like% ab_class_args |
2022-08-28 10:31:50 +02:00
atc_group1 %like% ab_class_args |
2023-02-09 13:07:39 +01:00
atc_group2 %like% ab_class_args ) %pm>%
pm_pull ( group ) %pm>%
unique ( ) %pm>%
tolower ( ) %pm>%
sort ( ) %pm>%
2021-06-04 21:07:55 +02:00
paste ( collapse = " /" )
2021-05-19 22:55:42 +02:00
}
find_ab_names <- function ( ab_group , n = 3 ) {
ab_group <- gsub ( " [^a-zA-Z|0-9]" , " .*" , ab_group )
2022-08-28 10:31:50 +02:00
2021-05-19 22:55:42 +02:00
# try popular first, they have DDDs
2022-10-14 13:02:50 +02:00
drugs <- AMR_env $ AB_lookup [which ( ( ! is.na ( AMR_env $ AB_lookup $ iv_ddd ) | ! is.na ( AMR_env $ AB_lookup $ oral_ddd ) ) &
AMR_env $ AB_lookup $ name %unlike% " " &
AMR_env $ AB_lookup $ group %like% ab_group &
AMR_env $ AB_lookup $ ab %unlike% " [0-9]$" ) , ] $ name
2021-05-19 22:55:42 +02:00
if ( length ( drugs ) < n ) {
# now try it all
2022-10-14 13:02:50 +02:00
drugs <- AMR_env $ AB_lookup [which ( ( AMR_env $ AB_lookup $ group %like% ab_group |
AMR_env $ AB_lookup $ atc_group1 %like% ab_group |
AMR_env $ AB_lookup $ atc_group2 %like% ab_group ) &
AMR_env $ AB_lookup $ ab %unlike% " [0-9]$" ) , ] $ name
2021-05-19 22:55:42 +02:00
}
2021-06-04 21:07:55 +02:00
if ( length ( drugs ) == 0 ) {
return ( " ??" )
}
2023-01-23 15:01:21 +01:00
vector_or (
ab_name ( sample ( drugs , size = min ( n , length ( drugs ) ) , replace = FALSE ) ,
tolower = TRUE ,
language = NULL
) ,
quotes = FALSE
2022-08-28 10:31:50 +02:00
)
2020-06-17 01:39:30 +02:00
}
2021-08-16 21:54:34 +02:00
2021-08-19 23:43:02 +02:00
message_agent_names <- function ( function_name , agents , ab_group = NULL , examples = " " , ab_class_args = NULL , call = NULL ) {
2021-12-11 13:41:31 +01:00
if ( message_not_thrown_before ( function_name , sort ( agents ) ) ) {
2021-08-16 21:54:34 +02:00
if ( length ( agents ) == 0 ) {
if ( is.null ( ab_group ) ) {
2022-11-13 13:44:25 +01:00
message_ ( " For `" , function_name , " ()` no antimicrobial drugs found" , examples , " ." )
2021-08-16 21:54:34 +02:00
} else if ( ab_group == " administrable_per_os" ) {
2022-11-13 13:44:25 +01:00
message_ ( " No orally administrable drugs found" , examples , " ." )
2021-08-16 21:54:34 +02:00
} else if ( ab_group == " administrable_iv" ) {
2022-11-13 13:44:25 +01:00
message_ ( " No IV administrable drugs found" , examples , " ." )
2021-08-16 21:54:34 +02:00
} else {
2022-11-13 13:44:25 +01:00
message_ ( " No antimicrobial drugs of class '" , ab_group , " ' found" , examples , " ." )
2021-08-16 21:54:34 +02:00
}
} else {
agents_formatted <- paste0 ( " '" , font_bold ( agents , collapse = NULL ) , " '" )
agents_names <- ab_name ( names ( agents ) , tolower = TRUE , language = NULL )
need_name <- generalise_antibiotic_name ( agents ) != generalise_antibiotic_name ( agents_names )
agents_formatted [need_name ] <- paste0 ( agents_formatted [need_name ] , " (" , agents_names [need_name ] , " )" )
2022-08-28 10:31:50 +02:00
message_ (
" For `" , function_name , " (" ,
ifelse ( function_name == " ab_class" ,
paste0 ( " \"" , ab_class_args , " \"" ) ,
ifelse ( ! is.null ( call ) ,
paste0 ( deparse ( call ) , collapse = " " ) ,
" "
)
) ,
" )` using " ,
ifelse ( length ( agents ) == 1 , " column " , " columns " ) ,
vector_and ( agents_formatted , quotes = FALSE , sort = FALSE )
)
2021-08-16 21:54:34 +02:00
}
}
}