1
0
mirror of https://github.com/msberends/AMR.git synced 2025-07-08 23:21:56 +02:00

(v1.2.0.9008) ab_class improvement

This commit is contained in:
2020-06-17 15:14:37 +02:00
parent c4d7412f36
commit ac12392da3
37 changed files with 619 additions and 362 deletions

View File

@ -63,14 +63,12 @@ filter_join_worker <- function(x, y, by = NULL, type = c("anti", "semi")) {
# No export, no Rd
addin_insert_in <- function() {
stopifnot_installed_package("rstudioapi")
get("insertText", envir = asNamespace("rstudioapi"))(" %in% ")
import_fn("insertText", "rstudioapi")(" %in% ")
}
# No export, no Rd
addin_insert_like <- function() {
stopifnot_installed_package("rstudioapi")
get("insertText", envir = asNamespace("rstudioapi"))(" %like% ")
import_fn("insertText", "rstudioapi")(" %like% ")
}
check_dataset_integrity <- function() {
@ -186,12 +184,23 @@ stopifnot_installed_package <- function(package) {
# https://developer.r-project.org/Blog/public/2019/02/14/staged-install/index.html
sapply(package, function(x)
tryCatch(get(".packageName", envir = asNamespace(x)),
error = function(e) stop("package '", x, "' required but not installed.",
"\nTry to install it with: install.packages(\"", x, "\")",
call. = FALSE)))
error = function(e) {
if (package == "rstudioapi") {
stop("This function only works in RStudio.", call. = FALSE)
} else {
stop("package '", x, "' required but not installed.",
"\nTry to install it with: install.packages(\"", x, "\")",
call. = FALSE)
}
}))
return(invisible())
}
import_fn <- function(name, pkg) {
stopifnot_installed_package(pkg)
get(name, envir = asNamespace(pkg))
}
stopifnot_msg <- function(expr, msg) {
if (!isTRUE(expr)) {
stop(msg, call. = FALSE)
@ -245,7 +254,7 @@ dataset_UTF8_to_ASCII <- function(df) {
df
}
has_colour <- function () {
has_colour <- function() {
# this is a base R version of crayon::has_color
enabled <- getOption("crayon.enabled")
if (!is.null(enabled)) {
@ -276,7 +285,7 @@ has_colour <- function () {
}
return(FALSE)
}
emacs_version <- function () {
emacs_version <- function() {
ver <- Sys.getenv("INSIDE_EMACS")
if (ver == "") {
return(NA_integer_)

View File

@ -22,6 +22,7 @@
#' Antibiotic class selectors
#'
#' Use these selection helpers inside any function that allows [Tidyverse selections](https://tidyselect.r-lib.org/reference/language.html), like `dplyr::select()` or `tidyr::pivot_longer()`. They help to select the columns of antibiotics that are of a specific antibiotic class, without the need to define the columns or antibiotic abbreviations.
#' @inheritParams filter_ab_class
#' @details All columns will be searched for known antibiotic names, abbreviations, brand names and codes (ATC, EARS-Net, WHO, etc.). This means that a selector like e.g. [aminoglycosides()] will pick up column names like 'gen', 'genta', 'J01GB03', 'tobra', 'Tobracin', etc.
#'
#' These functions only work if the `tidyselect` package is installed, that comes with the `dplyr` package. An error will be thrown if `tidyselect` package is not installed, or if the functions are used outside a function that allows Tidyverse selections like `select()` or `pivot_longer()`.
@ -36,119 +37,138 @@
#' example_isolates %>%
#' select(carbapenems())
#'
#'
#' # this will select columns 'mo', 'AMK', 'GEN', 'KAN' and 'TOB':
#' example_isolates %>%
#' select(mo, aminoglycosides())
#'
#' # this will select columns 'mo' and all antimycobacterial drugs ('RIF'):
#' example_isolates %>%
#' select(mo, ab_class("mycobact"))
#'
#'
#' # get bug/drug combinations for only macrolides in Gram-positives:
#' example_isolates %>%
#' filter(mo_gramstain(mo) %like% "pos") %>%
#' select(mo, macrolides()) %>%
#' bug_drug_combinations() %>%
#' format()
#'
#'
#' data.frame(irrelevant = "value",
#' J01CA01 = "S") %>% # ATC code of ampicillin
#' select(penicillins()) # so the 'J01CA01' column is selected
#'
#'
#' }
ab_class <- function(ab_class) {
ab_selector(ab_class, function_name = "ab_class")
}
#' @rdname antibiotic_class_selectors
#' @export
aminoglycosides <- function() {
ab_selector("aminoglycoside")
ab_selector("aminoglycoside", function_name = "aminoglycosides")
}
#' @rdname antibiotic_class_selectors
#' @export
carbapenems <- function() {
ab_selector("carbapenem")
ab_selector("carbapenem", function_name = "carbapenems")
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins <- function() {
ab_selector("cephalosporin")
ab_selector("cephalosporin", function_name = "cephalosporins")
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_1st <- function() {
ab_selector("cephalosporins.*1")
ab_selector("cephalosporins.*1", function_name = "cephalosporins_1st")
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_2nd <- function() {
ab_selector("cephalosporins.*2")
ab_selector("cephalosporins.*2", function_name = "cephalosporins_2nd")
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_3rd <- function() {
ab_selector("cephalosporins.*3")
ab_selector("cephalosporins.*3", function_name = "cephalosporins_3rd")
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_4th <- function() {
ab_selector("cephalosporins.*4")
ab_selector("cephalosporins.*4", function_name = "cephalosporins_4th")
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_5th <- function() {
ab_selector("cephalosporins.*5")
ab_selector("cephalosporins.*5", function_name = "cephalosporins_5th")
}
#' @rdname antibiotic_class_selectors
#' @export
fluoroquinolones <- function() {
ab_selector("fluoroquinolone")
ab_selector("fluoroquinolone", function_name = "fluoroquinolones")
}
#' @rdname antibiotic_class_selectors
#' @export
glycopeptides <- function() {
ab_selector("glycopeptide")
ab_selector("glycopeptide", function_name = "glycopeptides")
}
#' @rdname antibiotic_class_selectors
#' @export
macrolides <- function() {
ab_selector("macrolide")
ab_selector("macrolide", function_name = "macrolides")
}
#' @rdname antibiotic_class_selectors
#' @export
penicillins <- function() {
ab_selector("penicillin")
ab_selector("penicillin", function_name = "penicillins")
}
#' @rdname antibiotic_class_selectors
#' @export
tetracyclines <- function() {
ab_selector("tetracycline")
ab_selector("tetracycline", function_name = "tetracyclines")
}
ab_selector <- function(ab_class, vars = NULL) {
stopifnot_installed_package("tidyselect")
peek_vars_tidyselect <- get("peek_vars", envir = asNamespace("tidyselect"))
vars_vct <- peek_vars_tidyselect(fn = ab_class)
ab_selector <- function(ab_class, function_name) {
peek_vars_tidyselect <- import_fn("peek_vars", "tidyselect")
vars_vct <- peek_vars_tidyselect(fn = function_name)
vars_df <- data.frame(as.list(vars_vct))[0, , drop = FALSE]
colnames(vars_df) <- vars_vct
ab_in_data <- suppressMessages(get_column_abx(vars_df))
if (length(ab_in_data) == 0) {
message(font_blue("NOTE: no antimicrobial agents found."))
return(NULL)
}
ab_reference <- subset(antibiotics,
group %like% ab_class |
atc_group1 %like% ab_class |
atc_group2 %like% ab_class)
ab_group <- find_ab_group(ab_class)
if (ab_group == "") {
ab_group <- paste0("'", ab_class, "'")
examples <- ""
} else {
examples <- paste0(" (such as ", find_ab_names(ab_class, 2), ")")
}
# get the columns with a group names in the chosen ab class
agents <- ab_in_data[names(ab_in_data) %in% ab_reference$ab]
if (length(agents) == 0) {
message(font_blue(paste0("NOTE: no antimicrobial agents of class ", ab_group,
" found (such as ", find_ab_names(ab_class, 2),
").")))
message(font_blue(paste0("NOTE: No antimicrobial agents of class ", ab_group,
" found", examples, ".")))
} else {
message(font_blue(paste0("Selecting ", ab_group, ": ",
paste(paste0("`", font_bold(agents, collapse = NULL),

View File

@ -76,15 +76,14 @@ atc_online_property <- function(atc_code,
administration = "O",
url = "https://www.whocc.no/atc_ddd_index/?code=%s&showdescription=no") {
stopifnot_installed_package(c("curl", "rvest", "xml2"))
has_internet <- get("has_internet", envir = asNamespace("curl"))
html_attr <- get("html_attr", envir = asNamespace("rvest"))
html_children <- get("html_children", envir = asNamespace("rvest"))
html_node <- get("html_node", envir = asNamespace("rvest"))
html_nodes <- get("html_nodes", envir = asNamespace("rvest"))
html_table <- get("html_table", envir = asNamespace("rvest"))
html_text <- get("html_text", envir = asNamespace("rvest"))
read_html <- get("read_html", envir = asNamespace("xml2"))
has_internet <- import_fn("has_internet", "curl")
html_attr <- import_fn("html_attr", "rvest")
html_children <- import_fn("html_children", "rvest")
html_node <- import_fn("html_node", "rvest")
html_nodes <- import_fn("html_nodes", "rvest")
html_table <- import_fn("html_table", "rvest")
html_text <- import_fn("html_text", "rvest")
read_html <- import_fn("read_html", "xml2")
check_dataset_integrity()

View File

@ -62,6 +62,9 @@ bug_drug_combinations <- function(x,
if (!is.data.frame(x)) {
stop("`x` must be a data frame.", call. = FALSE)
}
if (!any(sapply(x, is.rsi), na.rm = TRUE)) {
stop("No columns with class <rsi> found. See ?as.rsi.", call. = FALSE)
}
# try to find columns based on type
# -- mo
@ -72,12 +75,13 @@ bug_drug_combinations <- function(x,
stop("`col_mo` must be set.", call. = FALSE)
}
x_class <- class(x)
x <- as.data.frame(x, stringsAsFactors = FALSE)
x[, col_mo] <- FUN(x[, col_mo, drop = TRUE])
x <- x[, c(col_mo, names(which(sapply(x, is.rsi))))]
x <- x[, c(col_mo, names(which(sapply(x, is.rsi)))), drop = FALSE]
unique_mo <- sort(unique(x[, col_mo, drop = TRUE]))
out <- data.frame(
mo = character(0),
ab = character(0),
@ -85,10 +89,10 @@ bug_drug_combinations <- function(x,
I = integer(0),
R = integer(0),
total = integer(0))
for (i in seq_len(length(unique_mo))) {
# filter on MO group and only select R/SI columns
x_mo_filter <- x[which(x[, col_mo, drop = TRUE] == unique_mo[i]), names(which(sapply(x, is.rsi)))]
x_mo_filter <- x[which(x[, col_mo, drop = TRUE] == unique_mo[i]), names(which(sapply(x, is.rsi))), drop = FALSE]
# turn and merge everything
pivot <- lapply(x_mo_filter, function(x) {
m <- as.matrix(table(x))
@ -103,8 +107,8 @@ bug_drug_combinations <- function(x,
total = merged$S + merged$I + merged$R)
out <- rbind(out, out_group)
}
structure(.Data = out, class = c("bug_drug_combinations", class(x)))
structure(.Data = out, class = c("bug_drug_combinations", x_class))
}
#' @method format bug_drug_combinations
@ -121,6 +125,7 @@ format.bug_drug_combinations <- function(x,
decimal.mark = getOption("OutDec"),
big.mark = ifelse(decimal.mark == ",", ".", ","),
...) {
x <- as.data.frame(x, stringsAsFactors = FALSE)
x <- subset(x, total >= minimum)
if (remove_intrinsic_resistant == TRUE) {
@ -221,6 +226,8 @@ format.bug_drug_combinations <- function(x,
#' @method print bug_drug_combinations
#' @export
print.bug_drug_combinations <- function(x, ...) {
print(as.data.frame(x, stringsAsFactors = FALSE))
message(font_blue("NOTE: Use 'format()' on this result to get a publicable/printable format."))
x_class <- class(x)
print(structure(x, class = x_class[x_class != "bug_drug_combinations"]),
...)
message(font_blue("NOTE: Use 'format()' on this result to get a publishable/printable format."))
}

View File

@ -206,7 +206,7 @@ eucast_rules <- function(x,
"\n\nThis may overwrite your existing data if you use e.g.:",
"\ndata <- eucast_rules(data, verbose = TRUE)\n\nDo you want to continue?")
if ("rstudioapi" %in% rownames(utils::installed.packages())) {
showQuestion <- get("showQuestion", envir = asNamespace("rstudioapi"))
showQuestion <- import_fn("showQuestion", "rstudioapi")
q_continue <- showQuestion("Using verbose = TRUE with eucast_rules()", txt)
} else {
q_continue <- utils::menu(choices = c("OK", "Cancel"), graphics = FALSE, title = txt)

View File

@ -26,10 +26,10 @@
#' Lifecycles of functions in the `AMR` package
#' @name lifecycle
#' @rdname lifecycle
#' @description Functions in this `AMR` package are categorised using [the lifecycle circle of the `tidyverse` as found on www.tidyverse.org/lifecycle](https://www.tidyverse.org/lifecycle).
#' @description Functions in this `AMR` package are categorised using [the lifecycle circle of the Tidyverse as found on www.tidyverse.org/lifecycle](https://www.Tidyverse.org/lifecycle).
#'
#' \if{html}{\figure{lifecycle_tidyverse.svg}{options: height=200px style=margin-bottom:5px} \cr}
#' This page contains a section for every lifecycle (with text borrowed from the aforementioned `tidyverse` website), so they can be used in the manual pages of the functions.
#' \if{html}{\figure{lifecycle_Tidyverse.svg}{options: height=200px style=margin-bottom:5px} \cr}
#' This page contains a section for every lifecycle (with text borrowed from the aforementioned Tidyverse website), so they can be used in the manual pages of the functions.
#' @section Experimental lifecycle:
#' \if{html}{\figure{lifecycle_experimental.svg}{options: style=margin-bottom:5px} \cr}
#' The [lifecycle][AMR::lifecycle] of this function is **experimental**. An experimental function is in early stages of development. The unlying code might be changing frequently. Experimental functions might be removed without deprecation, so you are generally best off waiting until a function is more mature before you use it in production code. Experimental functions are only available in development versions of this `AMR` package and will thus not be included in releases that are submitted to CRAN, since such functions have not yet matured enough.

View File

@ -95,7 +95,7 @@ mdro <- function(x,
"\n\nThis may overwrite your existing data if you use e.g.:",
"\ndata <- mdro(data, verbose = TRUE)\n\nDo you want to continue?")
if ("rstudioapi" %in% rownames(utils::installed.packages())) {
showQuestion <- get("showQuestion", envir = asNamespace("rstudioapi"))
showQuestion <- import_fn("showQuestion", "rstudioapi")
q_continue <- showQuestion("Using verbose = TRUE with mdro()", txt)
} else {
q_continue <- utils::menu(choices = c("OK", "Cancel"), graphics = FALSE, title = txt)

6
R/mo.R
View File

@ -152,7 +152,7 @@
#' \dontrun{
#' df$mo <- as.mo(df$microorganism_name)
#'
#' # the select function of tidyverse is also supported:
#' # the select function of the Tidyverse is also supported:
#' library(dplyr)
#' df$mo <- df %>%
#' select(microorganism_name) %>%
@ -1805,13 +1805,13 @@ parse_and_convert <- function(x) {
if (NCOL(x) > 2) {
stop("A maximum of two columns is allowed.", call. = FALSE)
} else if (NCOL(x) == 2) {
# support tidyverse selection like: df %>% select(colA, colB)
# support Tidyverse selection like: df %>% select(colA, colB)
# paste these columns together
x <- as.data.frame(x, stringsAsFactors = FALSE)
colnames(x) <- c("A", "B")
x <- paste(x$A, x$B)
} else {
# support tidyverse selection like: df %>% select(colA)
# support Tidyverse selection like: df %>% select(colA)
x <- as.data.frame(x, stringsAsFactors = FALSE)[[1]]
}
}

View File

@ -135,8 +135,7 @@ set_mo_source <- function(path) {
} else if (path %like% "[.]xlsx?$") {
# is Excel file (old or new)
stopifnot_installed_package("readxl")
read_excel <- get("read_excel", envir = asNamespace("readxl"))
read_excel <- import_fn("read_excel", "readxl")
df <- read_excel(path)
} else if (path %like% "[.]tsv$") {

View File

@ -40,7 +40,7 @@
#'
#' **Remember that you should filter your table to let it contain only first isolates!** This is needed to exclude duplicates and to reduce selection bias. Use [first_isolate()] to determine them in your data set.
#'
#' These functions are not meant to count isolates, but to calculate the proportion of resistance/susceptibility. Use the `count()`][AMR::count()] functions to count isolates. The function [susceptibility()] is essentially equal to `count_susceptible() / count_all()`. *Low counts can influence the outcome - the `proportion` functions may camouflage this, since they only return the proportion (albeit being dependent on the `minimum` parameter).*
#' These functions are not meant to count isolates, but to calculate the proportion of resistance/susceptibility. Use the [`count()`][AMR::count()] functions to count isolates. The function [susceptibility()] is essentially equal to `count_susceptible() / count_all()`. *Low counts can influence the outcome - the `proportion` functions may camouflage this, since they only return the proportion (albeit being dependent on the `minimum` parameter).*
#'
#' The function [proportion_df()] takes any variable from `data` that has an [`rsi`] class (created with [as.rsi()]) and calculates the proportions R, I and S. It also supports grouped variables. The function [rsi_df()] works exactly like [proportion_df()], but adds the number of isolates.
#' @section Combination therapy:

View File

@ -316,9 +316,9 @@ plot.resistance_predict <- function(x, main = paste("Resistance Prediction of",
}
# get plot() generic; this was moved from the 'graphics' pkg to the 'base' pkg in R 4.0.0
if (as.integer(R.Version()$major) >= 4) {
plot <- get("plot", envir = asNamespace("base"))
plot <- import_fn("plot", "base")
} else {
plot <- get("plot", envir = asNamespace("graphics"))
plot <- import_fn("plot", "graphics")
}
plot(x = x$year,
y = x$value,

View File

@ -594,9 +594,9 @@ plot.rsi <- function(x,
# get plot() generic; this was moved from the 'graphics' pkg to the 'base' pkg in R 4.0.0
if (as.integer(R.Version()$major) >= 4) {
plot <- get("plot", envir = asNamespace("base"))
plot <- import_fn("plot", "base")
} else {
plot <- get("plot", envir = asNamespace("graphics"))
plot <- import_fn("plot", "graphics")
}
plot(x = data$x,
y = data$s,