mirror of https://github.com/msberends/AMR.git
203 lines
7.8 KiB
R
Executable File
203 lines
7.8 KiB
R
Executable File
# ==================================================================== #
|
|
# TITLE #
|
|
# Antimicrobial Resistance (AMR) Analysis #
|
|
# #
|
|
# SOURCE #
|
|
# https://gitlab.com/msberends/AMR #
|
|
# #
|
|
# LICENCE #
|
|
# (c) 2019 Berends MS (m.s.berends@umcg.nl), Luz CF (c.f.luz@umcg.nl) #
|
|
# #
|
|
# 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. #
|
|
# #
|
|
# This R package was created for academic research and was publicly #
|
|
# released in the hope that it will be useful, but it comes WITHOUT #
|
|
# ANY WARRANTY OR LIABILITY. #
|
|
# Visit our website for more info: https://msberends.gitlab.io/AMR. #
|
|
# ==================================================================== #
|
|
|
|
# No export, no Rd
|
|
addin_insert_in <- function() {
|
|
rstudioapi::insertText(" %in% ")
|
|
}
|
|
|
|
# No export, no Rd
|
|
addin_insert_like <- function() {
|
|
rstudioapi::insertText(" %like% ")
|
|
}
|
|
|
|
# No export, no Rd
|
|
# works exactly like round(), but rounds `round(44.55, 1)` as 44.6 instead of 44.5 and adds decimal zeroes until `digits` is reached
|
|
round2 <- function(x, digits = 0, force_zero = TRUE) {
|
|
# https://stackoverflow.com/a/12688836/4575331
|
|
val <- (trunc((abs(x) * 10 ^ digits) + 0.5) / 10 ^ digits) * sign(x)
|
|
if (digits > 0 & force_zero == TRUE) {
|
|
val[val != as.integer(val)] <- paste0(val[val != as.integer(val)],
|
|
strrep("0", max(0, digits - nchar(gsub(".*[.](.*)$", "\\1", val[val != as.integer(val)])))))
|
|
}
|
|
val
|
|
}
|
|
|
|
# No export, no Rd
|
|
percent <- function(x, round = 1, force_zero = FALSE, decimal.mark = getOption("OutDec"), ...) {
|
|
|
|
decimal.mark.options <- getOption("OutDec")
|
|
options(OutDec = ".")
|
|
|
|
val <- round2(x, round + 2, force_zero = FALSE) # round up 0.5
|
|
val <- round(x = val * 100, digits = round) # remove floating point error
|
|
|
|
if (force_zero == TRUE) {
|
|
if (any(val == as.integer(val) & !is.na(val))) {
|
|
# add zeroes to all integers
|
|
val[val == as.integer(as.character(val))] <- paste0(val[val == as.integer(val)], ".", strrep(0, round))
|
|
}
|
|
# add extra zeroes if needed
|
|
val_decimals <- nchar(gsub(".*[.](.*)", "\\1", as.character(val)))
|
|
val[val_decimals < round] <- paste0(val[val_decimals < round], strrep(0, max(0, round - val_decimals)))
|
|
}
|
|
pct <- base::paste0(val, "%")
|
|
pct[pct %in% c("NA%", "NaN%")] <- NA_character_
|
|
if (decimal.mark != ".") {
|
|
pct <- gsub(".", decimal.mark, pct, fixed = TRUE)
|
|
}
|
|
options(OutDec = decimal.mark.options)
|
|
pct
|
|
}
|
|
|
|
check_available_columns <- function(tbl, col.list, info = TRUE) {
|
|
# check columns
|
|
col.list <- col.list[!is.na(col.list) & !is.null(col.list)]
|
|
names(col.list) <- col.list
|
|
col.list.bak <- col.list
|
|
# are they available as upper case or lower case then?
|
|
for (i in 1:length(col.list)) {
|
|
if (is.null(col.list[i]) | isTRUE(is.na(col.list[i]))) {
|
|
col.list[i] <- NA
|
|
} else if (toupper(col.list[i]) %in% colnames(tbl)) {
|
|
col.list[i] <- toupper(col.list[i])
|
|
} else if (tolower(col.list[i]) %in% colnames(tbl)) {
|
|
col.list[i] <- tolower(col.list[i])
|
|
} else if (!col.list[i] %in% colnames(tbl)) {
|
|
col.list[i] <- NA
|
|
}
|
|
}
|
|
if (!all(col.list %in% colnames(tbl))) {
|
|
if (info == TRUE) {
|
|
warning('Some columns do not exist and will be ignored: ',
|
|
col.list.bak[!(col.list %in% colnames(tbl))] %>% toString(),
|
|
'.\nTHIS MAY STRONGLY INFLUENCE THE OUTCOME.',
|
|
immediate. = TRUE,
|
|
call. = FALSE)
|
|
}
|
|
}
|
|
col.list
|
|
}
|
|
|
|
# Coefficient of variation (CV)
|
|
cv <- function(x, na.rm = TRUE) {
|
|
stats::sd(x, na.rm = na.rm) / base::abs(base::mean(x, na.rm = na.rm))
|
|
}
|
|
|
|
# Coefficient of dispersion, or coefficient of quartile variation (CQV).
|
|
# (Bonett et al., 2006: Confidence interval for a coefficient of quartile variation).
|
|
cqv <- function(x, na.rm = TRUE) {
|
|
fives <- stats::fivenum(x, na.rm = na.rm)
|
|
(fives[4] - fives[2]) / (fives[4] + fives[2])
|
|
}
|
|
|
|
# show bytes as kB/MB/GB
|
|
# size_humanreadable(123456) # 121 kB
|
|
# size_humanreadable(12345678) # 11.8 MB
|
|
size_humanreadable <- function(bytes, decimals = 1) {
|
|
bytes <- bytes %>% as.double()
|
|
# Adapted from:
|
|
# http://jeffreysambells.com/2012/10/25/human-readable-filesize-php
|
|
size <- c('B','kB','MB','GB','TB','PB','EB','ZB','YB')
|
|
factor <- floor((nchar(bytes) - 1) / 3)
|
|
# added slight improvement; no decimals for B and kB:
|
|
decimals <- rep(decimals, length(bytes))
|
|
decimals[size[factor + 1] %in% c('B', 'kB')] <- 0
|
|
|
|
out <- paste(sprintf(paste0("%.", decimals, "f"), bytes / (1024 ^ factor)), size[factor + 1])
|
|
out
|
|
}
|
|
|
|
#' @importFrom crayon blue bold red
|
|
#' @importFrom dplyr %>% pull
|
|
search_type_in_df <- function(tbl, type) {
|
|
# try to find columns based on type
|
|
found <- NULL
|
|
|
|
colnames(tbl) <- trimws(colnames(tbl))
|
|
|
|
# -- mo
|
|
if (type == "mo") {
|
|
if ("mo" %in% lapply(tbl, class)) {
|
|
found <- colnames(tbl)[lapply(tbl, class) == "mo"][1]
|
|
} else if (any(colnames(tbl) %like% "^(mo|microorganism|organism|bacteria)")) {
|
|
found <- colnames(tbl)[colnames(tbl) %like% "^(mo|microorganism|organism|bacteria)"][1]
|
|
} else if (any(colnames(tbl) %like% "species")) {
|
|
found <- colnames(tbl)[colnames(tbl) %like% "species"][1]
|
|
}
|
|
|
|
}
|
|
# -- key antibiotics
|
|
if (type == "keyantibiotics") {
|
|
if (any(colnames(tbl) %like% "^key.*(ab|antibiotics)")) {
|
|
found <- colnames(tbl)[colnames(tbl) %like% "^key.*(ab|antibiotics)"][1]
|
|
}
|
|
}
|
|
# -- date
|
|
if (type == "date") {
|
|
if (any(colnames(tbl) %like% "^(specimen date|specimen_date|spec_date)")) {
|
|
# WHONET support
|
|
found <- colnames(tbl)[colnames(tbl) %like% "^(specimen date|specimen_date|spec_date)"][1]
|
|
if (!any(class(tbl %>% pull(found)) %in% c("Date", "POSIXct"))) {
|
|
stop(red(paste0("ERROR: Found column `", bold(found), "` to be used as input for `col_", type,
|
|
"`, but this column contains no valid dates. Transform its values to valid dates first.")),
|
|
call. = FALSE)
|
|
}
|
|
} else {
|
|
for (i in 1:ncol(tbl)) {
|
|
if (any(class(tbl %>% pull(i)) %in% c("Date", "POSIXct"))) {
|
|
found <- colnames(tbl)[i]
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
# -- patient id
|
|
if (type == "patient_id") {
|
|
if (any(colnames(tbl) %like% "^(identification |patient|patid)")) {
|
|
found <- colnames(tbl)[colnames(tbl) %like% "^(identification |patient|patid)"][1]
|
|
}
|
|
}
|
|
# -- specimen
|
|
if (type == "specimen") {
|
|
if (any(colnames(tbl) %like% "(specimen type|spec_type)")) {
|
|
found <- colnames(tbl)[colnames(tbl) %like% "(specimen type|spec_type)"][1]
|
|
} else if (any(colnames(tbl) %like% "^(specimen)")) {
|
|
found <- colnames(tbl)[colnames(tbl) %like% "^(specimen)"][1]
|
|
}
|
|
}
|
|
|
|
if (!is.null(found)) {
|
|
msg <- paste0("NOTE: Using column `", bold(found), "` as input for `col_", type, "`.")
|
|
if (type %in% c("keyantibiotics", "specimen")) {
|
|
msg <- paste(msg, "Use", bold(paste0("col_", type), " = FALSE"), "to prevent this.")
|
|
}
|
|
message(blue(msg))
|
|
}
|
|
found
|
|
}
|
|
|
|
stopifnot_installed_package <- function(package) {
|
|
if (!package %in% base::rownames(utils::installed.packages())) {
|
|
stop("this function requires the ", package, " package.", call. = FALSE)
|
|
}
|
|
}
|