1
0
mirror of https://github.com/msberends/AMR.git synced 2025-07-08 12:31:58 +02:00

(v1.4.0.9008) like variations

This commit is contained in:
2020-10-26 12:23:03 +01:00
parent f720c9ba0b
commit 760d69a3e0
64 changed files with 919 additions and 582 deletions

View File

@ -9,7 +9,7 @@
# (c) 2018-2020 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
# Diagnostics & Advice, and University Medical Center Groningen. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
@ -37,18 +37,18 @@ pm_left_join <- function(x, y, by = NULL, suffix = c(".x", ".y")) {
if (length(by) == 1) {
by <- rep(by, 2)
}
int_x <- colnames(x) %in% colnames(y) & colnames(x) != by[1]
int_y <- colnames(y) %in% colnames(x) & colnames(y) != by[2]
colnames(x)[int_x] <- paste0(colnames(x)[int_x], suffix[1L])
colnames(y)[int_y] <- paste0(colnames(y)[int_y], suffix[2L])
merged <- cbind(x,
y[match(x[, by[1], drop = TRUE],
y[, by[2], drop = TRUE]),
colnames(y)[!colnames(y) %in% colnames(x) & !colnames(y) == by[2]],
drop = FALSE])
rownames(merged) <- NULL
merged
}
@ -71,7 +71,42 @@ addin_insert_in <- function() {
# No export, no Rd
addin_insert_like <- function() {
import_fn("insertText", "rstudioapi")(" %like% ")
stop_ifnot_installed("rstudioapi")
# we want Ctrl/Cmd + L to iterate over %like%, %not_like% and %like_case%, so determine context first
getSourceEditorContext <- import_fn("getSourceEditorContext", "rstudioapi")
insertText <- import_fn("insertText", "rstudioapi")
modifyRange <- import_fn("insertText", "rstudioapi")
document_range <- import_fn("document_range", "rstudioapi")
document_position <- import_fn("document_position", "rstudioapi")
# setSelectionRanges <- import_fn("setSelectionRanges", "rstudioapi")
context <- getSourceEditorContext()
current_row <- context$selection[[1]]$range$end[1]
current_col <- context$selection[[1]]$range$end[2]
current_row_txt <- context$contents[current_row]
pos_preceded_by <- function(txt) {
substr(current_row_txt, current_col - nchar(txt), current_col) == txt
}
replace_pos <- function(old, with) {
modifyRange(document_range(document_position(current_row, current_col - nchar(old)),
document_position(current_row, current_col)),
text = with,
id = context$id)
}
if (pos_preceded_by(" %like% ")) {
replace_pos(" %like% ", with = " %not_like% ")
} else if (pos_preceded_by(" %not_like% ")) {
replace_pos(" %not_like% ", with = " %like_case% ")
} else if (pos_preceded_by(" %like_case% ")) {
replace_pos(" %like_case% ", with = " %not_like_case% ")
} else if (pos_preceded_by(" %not_like_case% ")) {
replace_pos(" %not_like_case% ", with = " %like% ")
} else {
insertText(" %like% ")
}
}
check_dataset_integrity <- function() {
@ -88,13 +123,13 @@ check_dataset_integrity <- function() {
# check if other packages did not overwrite our data sets
tryCatch({
check_microorganisms <- all(c("mo", "fullname", "kingdom", "phylum",
"class", "order", "family", "genus",
"class", "order", "family", "genus",
"species", "subspecies", "rank",
"species_id", "source", "ref", "prevalence") %in% colnames(microorganisms),
na.rm = TRUE)
check_antibiotics <- all(c("ab", "atc", "cid", "name", "group",
check_antibiotics <- all(c("ab", "atc", "cid", "name", "group",
"atc_group1", "atc_group2", "abbreviations",
"synonyms", "oral_ddd", "oral_units",
"synonyms", "oral_ddd", "oral_units",
"iv_ddd", "iv_units", "loinc") %in% colnames(antibiotics),
na.rm = TRUE)
}, error = function(e) {
@ -107,10 +142,10 @@ check_dataset_integrity <- function() {
search_type_in_df <- function(x, type, info = TRUE) {
# try to find columns based on type
found <- NULL
x <- as.data.frame(x, stringsAsFactors = FALSE)
colnames(x) <- trimws(colnames(x))
# -- mo
if (type == "mo") {
if (any(sapply(x, is.mo))) {
@ -128,7 +163,7 @@ search_type_in_df <- function(x, type, info = TRUE) {
} else if (any(colnames(x) %like% "species")) {
found <- sort(colnames(x)[colnames(x) %like% "species"])[1]
}
}
# -- key antibiotics
if (type == "keyantibiotics") {
@ -180,7 +215,7 @@ search_type_in_df <- function(x, type, info = TRUE) {
}
}
}
if (!is.null(found) & info == TRUE) {
msg <- paste0("NOTE: Using column `", font_bold(found), "` as input for `col_", type, "`.")
if (type %in% c("keyantibiotics", "specimen")) {
@ -222,8 +257,8 @@ import_fn <- function(name, pkg, error_on_fail = TRUE) {
get(name, envir = asNamespace(pkg)),
error = function(e) {
if (isTRUE(error_on_fail)) {
stop_("function ", name, "() not found in package '", pkg,
"'. Please create an issue at https://github.com/msberends/AMR/issues. Many thanks!",
stop_("function ", name, "() not found in package '", pkg,
"'. Please create an issue at https://github.com/msberends/AMR/issues. Many thanks!",
call = FALSE)
} else {
return(NULL)
@ -231,6 +266,52 @@ import_fn <- function(name, pkg, error_on_fail = TRUE) {
})
}
# this alternative to the message() function:
# - wraps text to never break lines within words
# - ignores formatted text while wrapping
# - adds indentation dependent on the type of message (like NOTE)
# - add additional formatting functions like blue or bold text
message_ <- function(..., appendLF = TRUE, add_fn = list(font_blue)) {
msg <- paste0(c(...), collapse = "")
# we need to correct for already applied style, that adds text like "\033[31m\"
msg_stripped <- font_stripstyle(msg)
# where are the spaces now?
msg_stripped_wrapped <- paste0(strwrap(msg_stripped,
simplify = TRUE,
width = 0.95 * getOption("width")),
collapse = "\n")
msg_stripped_spaces <- which(unlist(strsplit(msg_stripped, "")) == " ")
msg_stripped_wrapped_spaces <- which(unlist(strsplit(msg_stripped_wrapped, "")) == " ")
# so these are the indices of spaces that need to be replaced
replace_spaces <- which(!msg_stripped_spaces %in% msg_stripped_wrapped_spaces)
# put it together
msg <- unlist(strsplit(msg, " "))
msg[replace_spaces] <- paste0(msg[replace_spaces], "\n")
msg <- paste0(msg, collapse = " ")
msg <- gsub("\n ", "\n", msg, fixed = TRUE)
if (msg_stripped %like% "^NOTE: ") {
indentation <- 6
} else {
indentation <- 0
}
msg <- gsub("\n", paste0("\n", strrep(" ", indentation)), msg, fixed = TRUE)
if (length(add_fn) > 0) {
if (!is.list(add_fn)) {
add_fn <- list(add_fn)
}
for (i in seq_len(length(add_fn))) {
msg <- add_fn[[i]](msg)
}
}
message(msg, appendLF = appendLF)
}
# this alternative to the stop() function:
# - adds the function name where the error was thrown
# - wraps text to never break lines within words
stop_ <- function(..., call = TRUE) {
msg <- paste0(c(...), collapse = "")
if (!isFALSE(call)) {
@ -340,10 +421,10 @@ meet_criteria <- function(object,
allow_NA = FALSE,
ignore.case = FALSE,
.call_depth = 0) { # depth in calling
obj_name <- deparse(substitute(object))
call_depth <- -2 - abs(.call_depth)
if (is.null(object)) {
stop_if(allow_NULL == FALSE, "argument `", obj_name, "` must not be NULL", call = call_depth)
return(invisible())
@ -352,7 +433,7 @@ meet_criteria <- function(object,
stop_if(allow_NA == FALSE, "argument `", obj_name, "` must not be NA", call = call_depth)
return(invisible())
}
vector_or <- function(v, quotes) {
if (length(v) == 1) {
return(paste0(ifelse(quotes, '"', ""), v, ifelse(quotes, '"', "")))
@ -361,32 +442,32 @@ meet_criteria <- function(object,
paste0(paste0(ifelse(quotes, '"', ""), v[seq_len(length(v) - 1)], ifelse(quotes, '"', ""), collapse = ", "),
" or ", paste0(ifelse(quotes, '"', ""), v[length(v)], ifelse(quotes, '"', "")))
}
if (!is.null(allow_class)) {
stop_ifnot(inherits(object, allow_class), "argument `", obj_name,
"` must ", # ifelse(allow_NULL, "be NULL or must ", ""),
"be of class ", vector_or(allow_class, quotes = TRUE),
stop_ifnot(inherits(object, allow_class), "argument `", obj_name,
"` must ", # ifelse(allow_NULL, "be NULL or must ", ""),
"be of class ", vector_or(allow_class, quotes = TRUE),
", not \"", paste(class(object), collapse = "/"), "\"",
call = call_depth)
# check data.frames for data
if (inherits(object, "data.frame")) {
stop_if(any(dim(object) == 0),
stop_if(any(dim(object) == 0),
"the data provided in argument `", obj_name,
"` must contain rows and columns (current dimensions: ",
"` must contain rows and columns (current dimensions: ",
paste(dim(object), collapse = " x "), ")",
call = call_depth)
}
}
if (!is.null(has_length)) {
stop_ifnot(length(object) %in% has_length, "argument `", obj_name,
"` must ", # ifelse(allow_NULL, "be NULL or must ", ""),
stop_ifnot(length(object) %in% has_length, "argument `", obj_name,
"` must ", # ifelse(allow_NULL, "be NULL or must ", ""),
"be of length ", vector_or(has_length, quotes = FALSE),
", not ", length(object),
call = call_depth)
}
if (!is.null(looks_like)) {
stop_ifnot(object %like% looks_like, "argument `", obj_name,
"` must ", # ifelse(allow_NULL, "be NULL or must ", ""),
stop_ifnot(object %like% looks_like, "argument `", obj_name,
"` must ", # ifelse(allow_NULL, "be NULL or must ", ""),
"resemble the regular expression \"", looks_like, "\"",
call = call_depth)
}
@ -395,16 +476,16 @@ meet_criteria <- function(object,
object <- tolower(object)
is_in <- tolower(is_in)
}
stop_ifnot(all(object %in% is_in, na.rm = TRUE), "argument `", obj_name,
stop_ifnot(all(object %in% is_in, na.rm = TRUE), "argument `", obj_name,
"` must be ",
ifelse(!is.null(has_length) && length(has_length) == 1 && has_length == 1, "one of: ", ""),
vector_or(is_in, quotes = TRUE),
vector_or(is_in, quotes = TRUE),
", not ", paste0("\"", object, "\"", collapse = "/"), "",
call = call_depth)
}
if (!is.null(contains_column_class)) {
stop_ifnot(any(sapply(object, function(col, columns_class = contains_column_class) inherits(col, columns_class)), na.rm = TRUE),
"the data provided in argument `", obj_name,
"the data provided in argument `", obj_name,
"` must contain at least one column of class <", contains_column_class, ">. ",
"See ?as.", contains_column_class, ".",
call = call_depth)
@ -463,7 +544,7 @@ has_colour <- function() {
if (Sys.getenv("TERM") == "dumb") {
return(FALSE)
}
grepl(pattern = "^screen|^xterm|^vt100|color|ansi|cygwin|linux",
grepl(pattern = "^screen|^xterm|^vt100|color|ansi|cygwin|linux",
x = Sys.getenv("TERM"),
ignore.case = TRUE,
perl = TRUE)
@ -560,7 +641,7 @@ progress_ticker <- function(n = 1, n_min = 0, ...) {
create_pillar_column <- function(x, ...) {
new_pillar_shaft_simple <- import_fn("new_pillar_shaft_simple", "pillar", error_on_fail = FALSE)
if (!is.null(new_pillar_shaft_simple)) {
new_pillar_shaft_simple(x, ...)
new_pillar_shaft_simple(x, ...)
} else {
# does not exist in package 'pillar' anymore
structure(list(x),
@ -622,12 +703,12 @@ round2 <- function(x, digits = 0, force_zero = TRUE) {
if (digits > 0 & force_zero == TRUE) {
values_trans <- val[val != as.integer(val) & !is.na(val)]
val[val != as.integer(val) & !is.na(val)] <- paste0(values_trans,
strrep("0",
max(0,
strrep("0",
max(0,
digits - nchar(
format(
as.double(
gsub(".*[.](.*)$",
gsub(".*[.](.*)$",
"\\1",
values_trans)),
scientific = FALSE)))))
@ -638,7 +719,7 @@ round2 <- function(x, digits = 0, force_zero = TRUE) {
# percentage from our other package: 'cleaner'
percentage <- function(x, digits = NULL, ...) {
# getdecimalplaces() function
getdecimalplaces <- function(x, minimum = 0, maximum = 3) {
if (maximum < minimum) {
@ -647,20 +728,20 @@ percentage <- function(x, digits = NULL, ...) {
if (minimum > maximum) {
minimum <- maximum
}
max_places <- max(unlist(lapply(strsplit(sub("0+$", "",
max_places <- max(unlist(lapply(strsplit(sub("0+$", "",
as.character(x * 100)), ".", fixed = TRUE),
function(y) ifelse(length(y) == 2, nchar(y[2]), 0))), na.rm = TRUE)
max(min(max_places,
maximum, na.rm = TRUE),
minimum, na.rm = TRUE)
}
# format_percentage() function
format_percentage <- function(x, digits = NULL, ...) {
if (is.null(digits)) {
digits <- getdecimalplaces(x)
}
# round right: percentage(0.4455) and format(as.percentage(0.4455), 1) should return "44.6%", not "44.5%"
x_formatted <- format(round2(as.double(x), digits = digits + 2) * 100,
scientific = FALSE,
@ -671,7 +752,7 @@ percentage <- function(x, digits = NULL, ...) {
x_formatted[!grepl(pattern = "^[0-9.,e-]+$", x = x)] <- NA_character_
x_formatted
}
# the actual working part
x <- as.double(x)
if (is.null(digits)) {
@ -688,12 +769,12 @@ percentage <- function(x, digits = NULL, ...) {
# see here for the full list: https://github.com/r-lib/backports
strrep <- function(x, times) {
x <- as.character(x)
if (length(x) == 0L)
if (length(x) == 0L)
return(x)
unlist(.mapply(function(x, times) {
if (is.na(x) || is.na(times))
if (is.na(x) || is.na(times))
return(NA_character_)
if (times <= 0L)
if (times <= 0L)
return("")
paste0(replicate(times, x), collapse = "")
}, list(x = x, times = times), MoreArgs = list()), use.names = FALSE)
@ -701,9 +782,9 @@ strrep <- function(x, times) {
trimws <- function(x, which = c("both", "left", "right")) {
which <- match.arg(which)
mysub <- function(re, x) sub(re, "", x, perl = TRUE)
if (which == "left")
if (which == "left")
return(mysub("^[ \t\r\n]+", x))
if (which == "right")
if (which == "right")
return(mysub("[ \t\r\n]+$", x))
mysub("[ \t\r\n]+$", mysub("^[ \t\r\n]+", x))
}