diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index a868e7d0..d4ef49d8 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -56,21 +56,24 @@ jobs: - {os: windows-latest, r: 'devel', allowfail: false} - {os: windows-latest, r: 'release', allowfail: false} - {os: windows-latest, r: 'oldrel', allowfail: false} - - {os: ubuntu-16.04, r: 'devel', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} + - {os: ubuntu-16.04, r: 'devel', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - {os: ubuntu-16.04, r: 'release', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - - {os: ubuntu-16.04, r: 'oldrel', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - - {os: ubuntu-20.04, r: 'devel', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} - - {os: ubuntu-20.04, r: 'release', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} - - {os: ubuntu-20.04, r: 'oldrel', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: ubuntu-16.04, r: 'oldrel', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - {os: ubuntu-16.04, r: '4.0', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - {os: ubuntu-16.04, r: '3.6', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - {os: ubuntu-16.04, r: '3.5', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - - {os: ubuntu-16.04, r: '3.4', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - - {os: ubuntu-16.04, r: '3.3', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} + - {os: ubuntu-16.04, r: '3.4', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} + - {os: ubuntu-16.04, r: '3.3', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - {os: ubuntu-16.04, r: '3.2', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - {os: ubuntu-16.04, r: '3.1', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} - - {os: ubuntu-16.04, r: '3.0', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} + - {os: ubuntu-16.04, r: '3.0', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} + - {os: ubuntu-20.04, r: 'devel', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: ubuntu-20.04, r: 'release', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: ubuntu-20.04, r: 'oldrel', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: ubuntu-20.04, r: '3.2', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: ubuntu-20.04, r: '3.1', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} - {os: ubuntu-20.04, r: '3.0', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + env: R_REMOTES_NO_ERRORS_FROM_WARNINGS: true RSPM: ${{ matrix.config.rspm }} @@ -92,21 +95,21 @@ jobs: shell: Rscript {0} - name: Cache R packages - if: runner.os != 'Windows' && matrix.config.r != '3.0' && matrix.config.r != '3.1' && matrix.config.r != '3.2' + if: runner.os != 'Windows' uses: actions/cache@v1 with: path: ${{ env.R_LIBS_USER }} - key: ${{ runner.os }}-r-${{ matrix.config.r }}-3-${{ hashFiles('.github/depends.Rds') }} - restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-3- + key: ${{ matrix.config.os }}-r-${{ matrix.config.r }}-3-${{ hashFiles('.github/depends.Rds') }} + restore-keys: ${{ matrix.config.os }}-r-${{ matrix.config.r }}-3- - name: Install Linux dependencies - if: runner.os == 'Linux' && matrix.config.r != '3.0' && matrix.config.r != '3.1' && matrix.config.r != '3.2' + if: runner.os == 'Linux' env: RHUB_PLATFORM: linux-x86_64-ubuntu-gcc + # update the below with sysreqs::sysreqs("DESCRIPTION") and check the "DEB" entries (for Ubuntu). + # we don't want to depend on the sysreqs pkg here, as it requires a quite new R version run: | - Rscript -e "remotes::install_github('r-hub/sysreqs')" - sysreqs=$(Rscript -e "cat(sysreqs::sysreq_commands('DESCRIPTION'))") - sudo -s eval "$sysreqs" + sudo apt install -y libssl-dev pandoc pandoc-citeproc libxml2-dev libicu-dev libcurl4-openssl-dev - name: Install macOS dependencies if: matrix.config.os == 'macOS-latest' && matrix.config.r == 'devel' @@ -114,10 +117,9 @@ jobs: brew install mariadb-connector-c - name: Install dependencies - if: matrix.config.r != '3.0' && matrix.config.r != '3.1' && matrix.config.r != '3.2' + if: always() run: | - remotes::install_deps(dependencies = TRUE) - remotes::install_cran("rcmdcheck") + utils::install.packages(strsplit(utils::packageDescription("AMR")$Suggests, ",\n")[[1]]) shell: Rscript {0} - name: Session info @@ -139,6 +141,7 @@ jobs: env: _R_CHECK_CRAN_INCOMING_: false _R_CHECK_FORCE_SUGGESTS_: false + # these are set already in --as-cran: _R_CHECK_LENGTH_1_CONDITION_: verbose _R_CHECK_LENGTH_1_LOGIC2_: verbose run: | diff --git a/DESCRIPTION b/DESCRIPTION index 04de6eda..57719f67 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: AMR -Version: 1.4.0.9055 -Date: 2020-12-31 +Version: 1.4.0.9056 +Date: 2021-01-03 Title: Antimicrobial Resistance Analysis Authors@R: c( person(role = c("aut", "cre"), diff --git a/NEWS.md b/NEWS.md index f6f50ecd..cea1f980 100755 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,5 @@ -# AMR 1.4.0.9055 -## Last updated: 31 December 2020 - +# AMR 1.4.0.9056 +## Last updated: 3 January 2021 ### New * Functions `get_episode()` and `is_new_episode()` to determine (patient) episodes which are not necessarily based on microorganisms. The `get_episode()` function returns the index number of the episode per group, while the `is_new_episode()` function returns values `TRUE`/`FALSE` to indicate whether an item in a vector is the start of a new episode. They also support `dplyr`s grouping (i.e. using `group_by()`): ```r @@ -11,7 +10,7 @@ ``` * Functions `mo_is_gram_negative()` and `mo_is_gram_positive()` as wrappers around `mo_gramstain()`. They always return `TRUE` or `FALSE` (except when the input is `NA` or the MO code is `UNKNOWN`), thus always return `FALSE` for species outside the taxonomic kingdom of Bacteria. * Function `mo_is_intrinsic_resistant()` to test for intrinsic resistance, based on [EUCAST Intrinsic Resistance and Unusual Phenotypes v3.2](https://www.eucast.org/expert_rules_and_intrinsic_resistance/) from 2020. -* Functions `random_mic()`, `random_disk()` and `random_rsi()` for random number generation. They take microorganism names and antibiotic names as input to make generation more realistic. +* Functions `random_mic()`, `random_disk()` and `random_rsi()` for random value generation. The functions `random_mic()` and `random_disk()` take microorganism names and antibiotic names as input to make generation more realistic. ### Changed * New argument `ampc_cephalosporin_resistance` in `eucast_rules()` to correct for AmpC de-repressed cephalosporin-resistant mutants @@ -22,7 +21,21 @@ * `as.rsi()` on a data.frame will not print a message anymore if the values are already clean R/SI values * If using `as.rsi()` on MICs or disk diffusion while there is intrinsic antimicrobial resistance, a warning will be thrown to remind about this * Fix for using `as.rsi()` on a `data.frame` that only contains one column for antibiotic interpretations -* Some functions are now context-aware when used inside `dplyr` verbs, such as `filter()`, `mutate()` and `summarise()`. This means that then the data argument does not need to be set anymore. This is the case for the new functions `mo_is_gram_negative()`, `mo_is_gram_positive()`, `mo_is_intrinsic_resistant()` and for the existing functions `first_isolate()`, `key_antibiotics()`, `mdro()`, `brmo()`, `mrgn()`, `mdr_tb()`, `mdr_cmi2012()`, `eucast_exceptional_phenotypes()`. This was already the case for antibiotic selection functions (such as using `penicillins()` in `dplyr::select()`). +* Some functions are now context-aware when used inside `dplyr` verbs, such as `filter()`, `mutate()` and `summarise()`. This means that then the data argument does not need to be set anymore. This is the case for the new functions: + * `mo_is_gram_negative()` + * `mo_is_gram_positive()` + * `mo_is_intrinsic_resistant()` + + ... and for the existing functions: + * `first_isolate()`, + * `key_antibiotics()`, + * `mdro()`, + * `brmo()`, + * `mrgn()`, + * `mdr_tb()`, + * `mdr_cmi2012()`, + * `eucast_exceptional_phenotypes()` + ```r # to select first isolates that are Gram-negative # and view results of cephalosporins and aminoglycosides: @@ -32,6 +45,12 @@ select(mo, cephalosporins(), aminoglycosides()) %>% as_tibble() ``` +* For antibiotic selection functions (such as `cephalosporins()`, `aminoglycosides()`) to select columns based on a certain antibiotic group, the dependency on the `tidyselect` package was removed, meaning that they can now also be used without the need to have this package installed and now also work in base R function calls: + ```r + # above example in base R: + example_isolates[which(first_isolate() & mo_is_gram_negative()), + c("mo", cephalosporins(), aminoglycosides())] + ``` * For all function arguments in the code, it is now defined what the exact type of user input should be (inspired by the [`typed`](https://github.com/moodymudskipper/typed) package). If the user input for a certain function does not meet the requirements for a specific argument (such as the class or length), an informative error will be thrown. This makes the package more robust and the use of it more reproducible and reliable. In total, more than 420 arguments were defined. * Fix for `set_mo_source()`, that previously would not remember the file location of the original file * Deprecated function `p_symbol()` that not really fits the scope of this package. It will be removed in a future version. See [here](https://github.com/msberends/AMR/blob/v1.4.0/R/p_symbol.R) for the source code to preserve it. @@ -47,7 +66,6 @@ * Fix for printing class in tibbles when all values are `NA` * Fix for `mo_shortname()` when the input contains `NA` * If `as.mo()` takes more than 30 seconds, some suggestions will be done to improve speed -* Lost dependency on the `tidyselect` package for using antibiotic selectors such as `carbapenems()` and `aminoglycosides()` ### Other * All messages and warnings thrown by this package now break sentences on whole words diff --git a/R/aa_helper_functions.R b/R/aa_helper_functions.R index baea8652..f0d84d02 100755 --- a/R/aa_helper_functions.R +++ b/R/aa_helper_functions.R @@ -527,43 +527,74 @@ meet_criteria <- function(object, } get_current_data <- function(arg_name, call) { - # this mimics dplyr::cur_data_all for users that use our context-aware functions in dplyr verbs - cur_data_all_dplyr <- import_fn("cur_data_all", "dplyr", error_on_fail = FALSE) - if (is.null(cur_data_all_dplyr)) { - # dplyr not installed - stop_("argument `", arg_name, "` is missing, with no default", call = call) + # try a (base R) method, by going over the complete system call stack with sys.frames() + not_set <- TRUE + frms <- lapply(sys.frames(), function(el) { + if (tryCatch(not_set == TRUE && ".data" %in% names(el) && is.data.frame(el$`.data`), error = function(e) FALSE)) { + # dplyr? - an element `.data` will be in the system call stack + not_set <<- FALSE + el$`.data` + } else if (tryCatch(not_set == TRUE && any(c("x", "xx") %in% names(el)), error = function(e) FALSE)) { + # otherwise try base R: + # an element `x` will be in this environment for only cols, e.g. `example_isolates[, carbapenems()]` + # an element `xx` will be in this environment for rows + cols, e.g. `example_isolates[c(1:3), carbapenems()]` + if (is.data.frame(el$xx)) { + not_set <<- FALSE + el$xx + } else if (is.data.frame(el$x)) { + not_set <<- FALSE + el$x + } else { + NULL + } + } else { + NULL + } + }) + vars_df <- tryCatch(frms[[which(!vapply(FUN.VALUE = logical(1), frms, is.null))]], error = function(e) NULL) + if (is.data.frame(vars_df)) { + return(vars_df) + } + + # nothing worked, so: + if (is.na(arg_name)) { + stop_("this function must be used inside valid dplyr selection verbs or inside a data.frame call", + call = call) + } else { + stop_("argument `", arg_name, "` is missing with no default ", + "or function not used inside a valid dplyr verb", + call = call) } - tryCatch(cur_data_all_dplyr(), - # dplyr installed, but not used inside dplyr verb - error = function(e) stop_("argument `", arg_name, "` is missing with no default ", - "or function not used inside a valid dplyr verb", - # tryCatch adds 4 system calls, subtract them - call = call - 4)) } -unique_call_id <- function() { - # combination of environment ID (like "0x7fed4ee8c848") - # and highest system call - c(envir = gsub("", "\\1", utils::capture.output(sys.frames()[[1]])), - call = paste0(deparse(sys.calls()[[1]]), collapse = "")) +unique_call_id <- function(entire_session = FALSE) { + if (entire_session == TRUE) { + c(envir = "session", + call = "session") + } else { + # combination of environment ID (like "0x7fed4ee8c848") + # and highest system call + c(envir = gsub("", "\\1", utils::capture.output(sys.frames()[[1]])), + call = paste0(deparse(sys.calls()[[1]]), collapse = "")) + } } -remember_thrown_message <- function(fn) { +remember_thrown_message <- function(fn, entire_session = FALSE) { # this is to prevent that messages/notes will be printed for every dplyr group # e.g. this would show a msg 4 times: example_isolates %>% group_by(hospital_id) %>% filter(mo_is_gram_negative()) - assign(x = paste0("uniquecall_", fn), - value = unique_call_id(), + assign(x = paste0("thrown_msg_", fn), + value = unique_call_id(entire_session = entire_session), envir = pkg_env) } -message_not_thrown_before <- function(fn) { - is.null(pkg_env[[paste0("uniquecall_", fn)]]) || !identical(pkg_env[[paste0("uniquecall_", fn)]], unique_call_id()) +message_not_thrown_before <- function(fn, entire_session = FALSE) { + is.null(pkg_env[[paste0("thrown_msg_", fn)]]) || !identical(pkg_env[[paste0("thrown_msg_", fn)]], unique_call_id(entire_session)) } reset_all_thrown_messages <- function() { # for unit tests, where the environment and highest system call do not change pkg_env_contents <- ls(envir = pkg_env) - rm(list = pkg_env_contents[pkg_env_contents %like% "^uniquecall_"], + rm(list = pkg_env_contents[pkg_env_contents %like% "^thrown_msg_"], envir = pkg_env) } @@ -571,7 +602,7 @@ has_colour <- function() { # this is a base R version of crayon::has_color, but disables colours on emacs if (Sys.getenv("EMACS") != "" || Sys.getenv("INSIDE_EMACS") != "") { - # disable on emacs, only supports 8 colours + # disable on emacs, which only supports 8 colours return(FALSE) } enabled <- getOption("crayon.enabled") diff --git a/R/ab_class_selectors.R b/R/ab_class_selectors.R index 18bc9ffb..673447ea 100644 --- a/R/ab_class_selectors.R +++ b/R/ab_class_selectors.R @@ -161,29 +161,8 @@ tetracyclines <- function() { ab_selector <- function(ab_class, function_name) { meet_criteria(ab_class, allow_class = "character", has_length = 1, .call_depth = 1) meet_criteria(function_name, allow_class = "character", has_length = 1, .call_depth = 1) - - for (i in seq_len(length(sys.frames()))) { - # dplyr? - if (".data" %in% names(sys.frames()[[i]])) { - vars_df <- sys.frames()[[i]]$`.data` - if (is.data.frame(vars_df)) { - break - } - } - # then try base R - an element `x` will be in the system call stack - vars_df <- tryCatch(sys.frames()[[i]]$x, error = function(e) NULL) - if (!is.null(vars_df) && is.data.frame(vars_df)) { - # when using e.g. example_isolates[, carbapenems()] or example_isolates %>% select(carbapenems()) - break - } else if (!is.null(vars_df) && is.list(vars_df)) { - # when using e.g. example_isolates %>% filter(across(carbapenems(), ~. == "R")) - vars_df <- tryCatch(as.data.frame(vars_df, stringsAsFactors = FALSE), error = function(e) NULL) - if (!is.null(vars_df)) { - break - } - } - } - stop_ifnot(is.data.frame(vars_df), "this function must be used inside dplyr selection verbs or within a data.frame call.", call = -2) + + vars_df <- get_current_data(arg_name = NA, call = -3) ab_in_data <- get_column_abx(vars_df, info = FALSE) if (length(ab_in_data) == 0) { diff --git a/R/mo_property.R b/R/mo_property.R index 9ddbb4dd..33cc7ba0 100755 --- a/R/mo_property.R +++ b/R/mo_property.R @@ -162,8 +162,8 @@ #' } mo_name <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_name") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_name") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -179,8 +179,8 @@ mo_fullname <- mo_name #' @export mo_shortname <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_shortname") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_shortname") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -217,8 +217,8 @@ mo_shortname <- function(x, language = get_locale(), ...) { #' @export mo_subspecies <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_subspecies") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_subspecies") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -230,8 +230,8 @@ mo_subspecies <- function(x, language = get_locale(), ...) { #' @export mo_species <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_species") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_species") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -243,8 +243,8 @@ mo_species <- function(x, language = get_locale(), ...) { #' @export mo_genus <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_genus") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_genus") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -256,8 +256,8 @@ mo_genus <- function(x, language = get_locale(), ...) { #' @export mo_family <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_family") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_family") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -269,8 +269,8 @@ mo_family <- function(x, language = get_locale(), ...) { #' @export mo_order <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_order") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_order") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -282,8 +282,8 @@ mo_order <- function(x, language = get_locale(), ...) { #' @export mo_class <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_class") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_class") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -295,8 +295,8 @@ mo_class <- function(x, language = get_locale(), ...) { #' @export mo_phylum <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_phylum") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_phylum") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -308,8 +308,8 @@ mo_phylum <- function(x, language = get_locale(), ...) { #' @export mo_kingdom <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_kingdom") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_kingdom") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -325,8 +325,8 @@ mo_domain <- mo_kingdom #' @export mo_type <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_type") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_type") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -338,8 +338,8 @@ mo_type <- function(x, language = get_locale(), ...) { #' @export mo_gramstain <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_gramstain") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_gramstain") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -376,8 +376,8 @@ mo_gramstain <- function(x, language = get_locale(), ...) { #' @export mo_is_gram_negative <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_is_gram_negative") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_is_gram_negative") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -395,8 +395,8 @@ mo_is_gram_negative <- function(x, language = get_locale(), ...) { #' @export mo_is_gram_positive <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_is_gram_positive") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_is_gram_positive") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -414,8 +414,8 @@ mo_is_gram_positive <- function(x, language = get_locale(), ...) { #' @export mo_is_intrinsic_resistant <- function(x, ab, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_is_intrinsic_resistant") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_is_intrinsic_resistant") } meet_criteria(x, allow_NA = TRUE) meet_criteria(ab, allow_NA = FALSE) @@ -433,11 +433,12 @@ mo_is_intrinsic_resistant <- function(x, ab, language = get_locale(), ...) { stop_("length of `x` and `ab` must be equal, or one of them must be of length 1.") } - # show used version number once - if (message_not_thrown_before("intrinsic_resistant_version")) { + # show used version number once per session (pkg_env will reload every session) + if (message_not_thrown_before("intrinsic_resistant_version", entire_session = TRUE)) { message_("Determining intrinsic resistance based on ", - format_eucast_version_nr(3.2, markdown = FALSE), ".") - remember_thrown_message("intrinsic_resistant_version") + format_eucast_version_nr(3.2, markdown = FALSE), ". ", + font_red("This note will be shown once per session.")) + remember_thrown_message("intrinsic_resistant_version", entire_session = TRUE) } # runs against internal vector: INTRINSIC_R (see zzz.R) @@ -448,8 +449,8 @@ mo_is_intrinsic_resistant <- function(x, ab, language = get_locale(), ...) { #' @export mo_snomed <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_snomed") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_snomed") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -461,8 +462,8 @@ mo_snomed <- function(x, language = get_locale(), ...) { #' @export mo_ref <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_ref") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_ref") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -474,8 +475,8 @@ mo_ref <- function(x, language = get_locale(), ...) { #' @export mo_authors <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_authors") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_authors") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -490,8 +491,8 @@ mo_authors <- function(x, language = get_locale(), ...) { #' @export mo_year <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_year") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_year") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -506,8 +507,8 @@ mo_year <- function(x, language = get_locale(), ...) { #' @export mo_rank <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_rank") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_rank") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -519,8 +520,8 @@ mo_rank <- function(x, language = get_locale(), ...) { #' @export mo_taxonomy <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_taxonomy") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_taxonomy") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -545,8 +546,8 @@ mo_taxonomy <- function(x, language = get_locale(), ...) { #' @export mo_synonyms <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_synonyms") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_synonyms") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -578,8 +579,8 @@ mo_synonyms <- function(x, language = get_locale(), ...) { #' @export mo_info <- function(x, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_info") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_info") } meet_criteria(x, allow_NA = TRUE) meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE) @@ -608,8 +609,8 @@ mo_info <- function(x, language = get_locale(), ...) { #' @export mo_url <- function(x, open = FALSE, language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_url") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_url") } meet_criteria(x, allow_NA = TRUE) meet_criteria(open, allow_class = "logical", has_length = 1) @@ -645,8 +646,8 @@ mo_url <- function(x, open = FALSE, language = get_locale(), ...) { #' @export mo_property <- function(x, property = "fullname", language = get_locale(), ...) { if (missing(x)) { - # this supports using in dplyr verbs: ... %>% filter(mo_is_intrinsic_resistant(ab = "amox")) - x <- find_mo_col("mo_property") + # this tries to find the data and an column + x <- find_mo_col(fn = "mo_property") } meet_criteria(x, allow_NA = TRUE) meet_criteria(property, allow_class = "character", has_length = 1, is_in = colnames(microorganisms)) @@ -700,7 +701,7 @@ mo_validate <- function(x, property, language, ...) { } find_mo_col <- function(fn) { - # this function tries to find an mo column using dplyr::cur_data_all() for mo_is_*() functions, + # this function tries to find an mo column in the data the function was called in, # which is useful when functions are used within dplyr verbs df <- get_current_data(arg_name = "x", call = -3) # will return an error if not found mo <- NULL diff --git a/data-raw/AMR_1.4.0.9055.tar.gz b/data-raw/AMR_1.4.0.9056.tar.gz similarity index 80% rename from data-raw/AMR_1.4.0.9055.tar.gz rename to data-raw/AMR_1.4.0.9056.tar.gz index 85ea6f61..c1c3c8fe 100644 Binary files a/data-raw/AMR_1.4.0.9055.tar.gz and b/data-raw/AMR_1.4.0.9056.tar.gz differ diff --git a/data-raw/reproduction_of_intrinsic_resistant.R b/data-raw/reproduction_of_intrinsic_resistant.R index 638c4097..13b25c4a 100644 --- a/data-raw/reproduction_of_intrinsic_resistant.R +++ b/data-raw/reproduction_of_intrinsic_resistant.R @@ -24,6 +24,7 @@ # ==================================================================== # library(AMR) +library(dplyr) int_resis <- data.frame(microorganism = microorganisms$mo, stringsAsFactors = FALSE) for (i in seq_len(nrow(antibiotics))) { int_resis$new <- as.rsi("S") @@ -45,3 +46,6 @@ int_resis2$microorganism <- mo_name(int_resis2$microorganism, language = NULL) intrinsic_resistant <- as.data.frame(int_resis2, stringsAsFactors = FALSE) usethis::use_data(intrinsic_resistant, internal = FALSE, overwrite = TRUE, version = 2, compress = "xz") rm(intrinsic_resistant) + +# AFTER THIS: +# DO NOT FORGET TO UPDATE THE VERSION NUMBER IN mo_is_intrinsic_resistant() diff --git a/docs/404.html b/docs/404.html index 4e157f9e..923581a4 100644 --- a/docs/404.html +++ b/docs/404.html @@ -81,7 +81,7 @@ AMR (for R) - 1.4.0.9055 + 1.4.0.9056 diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index c4564d6d..01c3cc91 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -81,7 +81,7 @@ AMR (for R) - 1.4.0.9055 + 1.4.0.9056 diff --git a/docs/articles/index.html b/docs/articles/index.html index 4e159a44..bc285408 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -81,7 +81,7 @@ AMR (for R) - 1.4.0.9055 + 1.4.0.9056 diff --git a/docs/authors.html b/docs/authors.html index 60584448..f41dcaed 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -81,7 +81,7 @@ AMR (for R) - 1.4.0.9055 + 1.4.0.9056 diff --git a/docs/index.html b/docs/index.html index e67a3cc4..4b5badce 100644 --- a/docs/index.html +++ b/docs/index.html @@ -43,7 +43,7 @@ AMR (for R) - 1.4.0.9055 + 1.4.0.9056 @@ -227,6 +227,8 @@ Since you are one of our users, we would like to know how you use the package an select(mo, aminoglycosides(), carbapenems()) #> NOTE: Using column 'mo' as input for mo_is_gram_negative() #> NOTE: Using column 'mo' as input for mo_is_intrinsic_resistant() +#> NOTE: Determining intrinsic resistance based on 'EUCAST Expert Rules' and +#> 'EUCAST Intrinsic Resistance and Unusual Phenotypes' v3.2 from 2020. #> Selecting aminoglycosides: 'AMK' (amikacin), 'GEN' (gentamicin), #> 'KAN' (kanamycin), 'TOB' (tobramycin) #> Selecting carbapenems: 'IPM' (imipenem), 'MEM' (meropenem) @@ -298,6 +300,12 @@ Since you are one of our users, we would like to know how you use the package an +

A base R equivalent would be:

+
+example_isolates$mo <- mo_fullname(example_isolates$mo)
+example_isolates[which(mo_is_gram_negative() &
+                         mo_is_intrinsic_resistant(ab = "cefotax")),
+                 c("mo", aminoglycosides(), carbapenems())]

@@ -339,7 +347,7 @@ Since you are one of our users, we would like to know how you use the package an Latest released version

CRAN CRANlogs

This package is available here on the official R network (CRAN), which has a peer-reviewed submission process. Install this package in R from CRAN by using the command:

-
+
 

It will be downloaded and installed automatically. For RStudio, click on the menu Tools > Install Packages… and then type in “AMR” and press Install.

Note: Not all functions on this website may be available in this latest release. To use all functions and data sets mentioned on this website, install the latest development version.

@@ -349,7 +357,7 @@ Since you are one of our users, we would like to know how you use the package an Latest development version

R-code-checkCodeFactor Codecov

The latest and unpublished development version can be installed from GitHub using:

-
+
 install.packages("remotes") 
 remotes::install_github("msberends/AMR")
diff --git a/docs/news/index.html b/docs/news/index.html index 172d21c9..a383bc88 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -81,7 +81,7 @@ AMR (for R) - 1.4.0.9055 + 1.4.0.9056
@@ -236,13 +236,13 @@ Source: NEWS.md
-
-

-AMR 1.4.0.9055 Unreleased +
+

+AMR 1.4.0.9056 Unreleased

-
+

-Last updated: 31 December 2020 +Last updated: 3 January 2021

@@ -259,7 +259,7 @@
  • Functions mo_is_gram_negative() and mo_is_gram_positive() as wrappers around mo_gramstain(). They always return TRUE or FALSE (except when the input is NA or the MO code is UNKNOWN), thus always return FALSE for species outside the taxonomic kingdom of Bacteria.

  • Function mo_is_intrinsic_resistant() to test for intrinsic resistance, based on EUCAST Intrinsic Resistance and Unusual Phenotypes v3.2 from 2020.

  • -
  • Functions random_mic(), random_disk() and random_rsi() for random number generation. They take microorganism names and antibiotic names as input to make generation more realistic.

  • +
  • Functions random_mic(), random_disk() and random_rsi() for random value generation. The functions random_mic() and random_disk() take microorganism names and antibiotic names as input to make generation more realistic.

  • @@ -280,7 +280,30 @@
  • -

    Some functions are now context-aware when used inside dplyr verbs, such as filter(), mutate() and summarise(). This means that then the data argument does not need to be set anymore. This is the case for the new functions mo_is_gram_negative(), mo_is_gram_positive(), mo_is_intrinsic_resistant() and for the existing functions first_isolate(), key_antibiotics(), mdro(), brmo(), mrgn(), mdr_tb(), mdr_cmi2012(), eucast_exceptional_phenotypes(). This was already the case for antibiotic selection functions (such as using penicillins() in dplyr::select()).

    +

    Some functions are now context-aware when used inside dplyr verbs, such as filter(), mutate() and summarise(). This means that then the data argument does not need to be set anymore. This is the case for the new functions:

    + +

    … and for the existing functions:

    +
     
     # to select first isolates that are Gram-negative 
    @@ -291,6 +314,14 @@
       select(mo, cephalosporins(), aminoglycosides()) %>% 
       as_tibble()
  • +
  • +

    For antibiotic selection functions (such as cephalosporins(), aminoglycosides()) to select columns based on a certain antibiotic group, the dependency on the tidyselect package was removed, meaning that they can now also be used without the need to have this package installed and now also work in base R function calls:

    +
    +
    +# above example in base R:
    +example_isolates[which(first_isolate() & mo_is_gram_negative()),
    +                 c("mo", cephalosporins(), aminoglycosides())]
    +
  • For all function arguments in the code, it is now defined what the exact type of user input should be (inspired by the typed package). If the user input for a certain function does not meet the requirements for a specific argument (such as the class or length), an informative error will be thrown. This makes the package more robust and the use of it more reproducible and reliable. In total, more than 420 arguments were defined.

  • Fix for set_mo_source(), that previously would not remember the file location of the original file

  • Deprecated function p_symbol() that not really fits the scope of this package. It will be removed in a future version. See here for the source code to preserve it.

  • @@ -306,7 +337,6 @@
  • Fix for printing class in tibbles when all values are NA

  • Fix for mo_shortname() when the input contains NA

  • If as.mo() takes more than 30 seconds, some suggestions will be done to improve speed

  • -
  • Lost dependency on the tidyselect package for using antibiotic selectors such as carbapenems() and aminoglycosides()

  • @@ -338,7 +368,7 @@
  • Data set intrinsic_resistant. This data set contains all bug-drug combinations where the ‘bug’ is intrinsic resistant to the ‘drug’ according to the latest EUCAST insights. It contains just two columns: microorganism and antibiotic.

    Curious about which enterococci are actually intrinsic resistant to vancomycin?

    -
    +
     
     library(AMR)
     library(dplyr)
    @@ -361,7 +391,7 @@
     
    • Support for using dplyr’s across() to interpret MIC values or disk zone diameters, which also automatically determines the column with microorganism names or codes.

      -
      +
       
       # until dplyr 1.0.0
       your_data %>% mutate_if(is.mic, as.rsi)
      @@ -379,7 +409,7 @@
       
    • Added intelligent data cleaning to as.disk(), so numbers can also be extracted from text and decimal numbers will always be rounded up:

      -
      +
       
       as.disk(c("disk zone: 23.4 mm", 23.4))
       #> Class <disk>
      @@ -440,7 +470,7 @@
       
    • Function ab_from_text() to retrieve antimicrobial drug names, doses and forms of administration from clinical texts in e.g. health care records, which also corrects for misspelling since it uses as.ab() internally

    • Tidyverse selection helpers for antibiotic classes, that help to select the columns of antibiotics that are of a specific antibiotic class, without the need to define the columns or antibiotic abbreviations. They can be used in any function that allows selection helpers, like dplyr::select() and tidyr::pivot_longer():

      -
      +
       
       library(dplyr)
       
      @@ -629,7 +659,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
       
    • Fixed important floating point error for some MIC comparisons in EUCAST 2020 guideline

    • Interpretation from MIC values (and disk zones) to R/SI can now be used with mutate_at() of the dplyr package:

      -
      +
       
       yourdata %>% 
         mutate_at(vars(antibiotic1:antibiotic25), as.rsi, mo = "E. coli")
      @@ -658,7 +688,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
       
      • Support for LOINC codes in the antibiotics data set. Use ab_loinc() to retrieve LOINC codes, or use a LOINC code for input in any ab_* function:

        -
        +
         
         ab_loinc("ampicillin")
         #> [1] "21066-6" "3355-5"  "33562-0" "33919-2" "43883-8" "43884-6" "87604-5"
        @@ -669,7 +699,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
         
      • Support for SNOMED CT codes in the microorganisms data set. Use mo_snomed() to retrieve SNOMED codes, or use a SNOMED code for input in any mo_* function:

        -
        +
         
         mo_snomed("S. aureus")
         #> [1] 115329001   3092008 113961008
        @@ -734,11 +764,11 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
         
        • If you were dependent on the old Enterobacteriaceae family e.g. by using in your code:

          -
          +
           
           if (mo_family(somebugs) == "Enterobacteriaceae") ...

          then please adjust this to:

          -
          +
           
           if (mo_order(somebugs) == "Enterobacterales") ...
        • @@ -752,7 +782,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
          • Functions susceptibility() and resistance() as aliases of proportion_SI() and proportion_R(), respectively. These functions were added to make it more clear that “I” should be considered susceptible and not resistant.

            -
            +
             
             library(dplyr)
             example_isolates %>%
            @@ -781,7 +811,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
             
          • More intelligent way of coping with some consonants like “l” and “r”

          • Added a score (a certainty percentage) to mo_uncertainties(), that is calculated using the Levenshtein distance:

            -
            +
             
             as.mo(c("Stafylococcus aureus",
                     "staphylokok aureuz"))
            @@ -840,14 +870,14 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
             
            • Determination of first isolates now excludes all ‘unknown’ microorganisms at default, i.e. microbial code "UNKNOWN". They can be included with the new argument include_unknown:

              -
              +
               
               first_isolate(..., include_unknown = TRUE)

              For WHONET users, this means that all records/isolates with organism code "con" (contamination) will be excluded at default, since as.mo("con") = "UNKNOWN". The function always shows a note with the number of ‘unknown’ microorganisms that were included or excluded.

            • For code consistency, classes ab and mo will now be preserved in any subsetting or assignment. For the sake of data integrity, this means that invalid assignments will now result in NA:

              -
              +
               
               # how it works in base R:
               x <- factor("A")
              @@ -872,7 +902,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
               
              • Function bug_drug_combinations() to quickly get a data.frame with the results of all bug-drug combinations in a data set. The column containing microorganism codes is guessed automatically and its input is transformed with mo_shortname() at default:

                -
                +
                 
                 x <- bug_drug_combinations(example_isolates)
                 #> NOTE: Using column `mo` as input for `col_mo`.
                @@ -895,13 +925,13 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 #> 4 Gram-negative AMX 227  0 405   632
                 #> NOTE: Use 'format()' on this result to get a publicable/printable format.

                You can format this to a printable format, ready for reporting or exporting to e.g. Excel with the base R format() function:

                -
                +
                 
                 format(x, combine_IR = FALSE)
              • Additional way to calculate co-resistance, i.e. when using multiple antimicrobials as input for portion_* functions or count_* functions. This can be used to determine the empiric susceptibility of a combination therapy. A new argument only_all_tested (which defaults to FALSE) replaces the old also_single_tested and can be used to select one of the two methods to count isolates and calculate portions. The difference can be seen in this example table (which is also on the portion and count help pages), where the %SI is being determined:

                -
                +
                 
                 # --------------------------------------------------------------------
                 #                     only_all_tested = FALSE  only_all_tested = TRUE
                @@ -923,7 +953,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 
              • tibble printing support for classes rsi, mic, disk, ab mo. When using tibbles containing antimicrobial columns, values S will print in green, values I will print in yellow and values R will print in red. Microbial IDs (class mo) will emphasise on the genus and species, not on the kingdom.

                -
                +
                 
                 # (run this on your own console, as this page does not support colour printing)
                 library(dplyr)
                @@ -1006,7 +1036,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 
                • Function rsi_df() to transform a data.frame to a data set containing only the microbial interpretation (S, I, R), the antibiotic, the percentage of S/I/R and the number of available isolates. This is a convenient combination of the existing functions count_df() and portion_df() to immediately show resistance percentages and number of available isolates:

                  -
                  +
                   
                   septic_patients %>%
                     select(AMX, CIP) %>%
                  @@ -1033,7 +1063,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                   
                • UPEC (Uropathogenic E. coli)

                All these lead to the microbial ID of E. coli:

                -
                +
                 
                 as.mo("UPEC")
                 # B_ESCHR_COL
                @@ -1138,7 +1168,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 
              • when all values are unique it now shows a message instead of a warning

              • support for boxplots:

                -
                +
                 
                 septic_patients %>% 
                   freq(age) %>% 
                @@ -1233,7 +1263,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 
              • New filters for antimicrobial classes. Use these functions to filter isolates on results in one of more antibiotics from a specific class:

                -
                +
                 
                 filter_aminoglycosides()
                 filter_carbapenems()
                @@ -1247,7 +1277,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 filter_macrolides()
                 filter_tetracyclines()

                The antibiotics data set will be searched, after which the input data will be checked for column names with a value in any abbreviations, codes or official names found in the antibiotics data set. For example:

                -
                +
                 
                 septic_patients %>% filter_glycopeptides(result = "R")
                 # Filtering on glycopeptide antibacterials: any of `vanc` or `teic` is R
                @@ -1256,7 +1286,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 
              • All ab_* functions are deprecated and replaced by atc_* functions:

                -
                +
                 
                 ab_property -> atc_property()
                 ab_name -> atc_name()
                @@ -1277,7 +1307,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 
              • New function age_groups() to split ages into custom or predefined groups (like children or elderly). This allows for easier demographic antimicrobial resistance analysis per age group.

              • New function ggplot_rsi_predict() as well as the base R plot() function can now be used for resistance prediction calculated with resistance_predict():

                -
                +
                 
                 x <- resistance_predict(septic_patients, col_ab = "amox")
                 plot(x)
                @@ -1285,13 +1315,13 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 
              • Functions filter_first_isolate() and filter_first_weighted_isolate() to shorten and fasten filtering on data sets with antimicrobial results, e.g.:

                -
                +
                 
                 septic_patients %>% filter_first_isolate(...)
                 # or
                 filter_first_isolate(septic_patients, ...)

                is equal to:

                -
                +
                 
                 septic_patients %>%
                   mutate(only_firsts = first_isolate(septic_patients, ...)) %>%
                @@ -1324,7 +1354,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                 
                • Now handles incorrect spelling, like i instead of y and f instead of ph:

                  -
                  +
                   
                   # mo_fullname() uses as.mo() internally
                   
                  @@ -1336,7 +1366,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                   
                • Uncertainty of the algorithm is now divided into four levels, 0 to 3, where the default allow_uncertain = TRUE is equal to uncertainty level 2. Run ?as.mo for more info about these levels.

                  -
                  +
                   
                   # equal:
                   as.mo(..., allow_uncertain = TRUE)
                  @@ -1351,7 +1381,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                   
                • All microbial IDs that found are now saved to a local file ~/.Rhistory_mo. Use the new function clean_mo_history() to delete this file, which resets the algorithms.

                • Incoercible results will now be considered ‘unknown’, MO code UNKNOWN. On foreign systems, properties of these will be translated to all languages already previously supported: German, Dutch, French, Italian, Spanish and Portuguese:

                  -
                  +
                   
                   mo_genus("qwerty", language = "es")
                   # Warning: 
                  @@ -1401,7 +1431,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                   
                  • Support for tidyverse quasiquotation! Now you can create frequency tables of function outcomes:

                    -
                    +
                     
                     # Determine genus of microorganisms (mo) in `septic_patients` data set:
                     # OLD WAY
                    @@ -1485,7 +1515,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                     
                  • Fewer than 3 characters as input for as.mo will return NA

                  • Function as.mo (and all mo_* wrappers) now supports genus abbreviations with “species” attached

                    -
                    +
                     
                     as.mo("E. species")        # B_ESCHR
                     mo_fullname("E. spp.")     # "Escherichia species"
                    @@ -1502,7 +1532,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                     
                    • Support for grouping variables, test with:

                      -
                      +
                       
                       septic_patients %>% 
                         group_by(hospital_id) %>% 
                      @@ -1510,7 +1540,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                       
                    • Support for (un)selecting columns:

                      -
                      +
                       
                       septic_patients %>% 
                         freq(hospital_id) %>% 
                      @@ -1590,7 +1620,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                       

                    They also come with support for German, Dutch, French, Italian, Spanish and Portuguese:

                    -
                    +
                     
                     mo_gramstain("E. coli")
                     # [1] "Gram negative"
                    @@ -1601,7 +1631,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                     mo_fullname("S. group A", language = "pt") # Portuguese
                     # [1] "Streptococcus grupo A"

                    Furthermore, former taxonomic names will give a note about the current taxonomic name:

                    -
                    +
                     
                     mo_gramstain("Esc blattae")
                     # Note: 'Escherichia blattae' (Burgess et al., 1973) was renamed 'Shimwellia blattae' (Priest and Barker, 2010)
                    @@ -1616,7 +1646,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                     
                  • Function is.rsi.eligible to check for columns that have valid antimicrobial results, but do not have the rsi class yet. Transform the columns of your raw data with: data %>% mutate_if(is.rsi.eligible, as.rsi)

                  • Functions as.mo and is.mo as replacements for as.bactid and is.bactid (since the microoganisms data set not only contains bacteria). These last two functions are deprecated and will be removed in a future release. The as.mo function determines microbial IDs using intelligent rules:

                    -
                    +
                     
                     as.mo("E. coli")
                     # [1] B_ESCHR_COL
                    @@ -1625,7 +1655,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                     as.mo("S group A")
                     # [1] B_STRPTC_GRA

                    And with great speed too - on a quite regular Linux server from 2007 it takes us less than 0.02 seconds to transform 25,000 items:

                    -
                    +
                     
                     thousands_of_E_colis <- rep("E. coli", 25000)
                     microbenchmark::microbenchmark(as.mo(thousands_of_E_colis), unit = "s")
                    @@ -1659,7 +1689,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                     
                  • Added three antimicrobial agents to the antibiotics data set: Terbinafine (D01BA02), Rifaximin (A07AA11) and Isoconazole (D01AC05)

                  • Added 163 trade names to the antibiotics data set, it now contains 298 different trade names in total, e.g.:

                    -
                    +
                     
                     ab_official("Bactroban")
                     # [1] "Mupirocin"
                    @@ -1676,7 +1706,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                     
                  • Added arguments minimum and as_percent to portion_df

                  • Support for quasiquotation in the functions series count_* and portions_*, and n_rsi. This allows to check for more than 2 vectors or columns.

                    -
                    +
                     
                     septic_patients %>% select(amox, cipr) %>% count_IR()
                     # which is the same as:
                    @@ -1696,12 +1726,12 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
                     
                  • Added longest en shortest character length in the frequency table (freq) header of class character

                  • Support for types (classes) list and matrix for freq

                    -
                    +
                     
                     my_matrix = with(septic_patients, matrix(c(age, gender), ncol = 2))
                     freq(my_matrix)

                    For lists, subsetting is possible:

                    -
                    +
                     
                     my_list = list(age = septic_patients$age, gender = septic_patients$gender)
                     my_list %>% freq(age)
                    diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml
                    index 5f348f04..20be7fcd 100644
                    --- a/docs/pkgdown.yml
                    +++ b/docs/pkgdown.yml
                    @@ -12,7 +12,7 @@ articles:
                       datasets: datasets.html
                       resistance_predict: resistance_predict.html
                       welcome_to_AMR: welcome_to_AMR.html
                    -last_built: 2020-12-31T12:43Z
                    +last_built: 2021-01-03T22:35Z
                     urls:
                       reference: https://msberends.github.io/AMR//reference
                       article: https://msberends.github.io/AMR//articles
                    diff --git a/docs/reference/index.html b/docs/reference/index.html
                    index 3171c83f..40cb648c 100644
                    --- a/docs/reference/index.html
                    +++ b/docs/reference/index.html
                    @@ -81,7 +81,7 @@
                           
                           
                             AMR (for R)
                    -        1.4.0.9055
                    +        1.4.0.9056
                           
                         
                    diff --git a/docs/survey.html b/docs/survey.html index e54ae32b..b64c607b 100644 --- a/docs/survey.html +++ b/docs/survey.html @@ -81,7 +81,7 @@ AMR (for R) - 1.4.0.9055 + 1.4.0.9056
                    diff --git a/git_premaster.sh b/git_premaster.sh index 49921590..a41e7a45 100755 --- a/git_premaster.sh +++ b/git_premaster.sh @@ -123,9 +123,9 @@ echo echo "••••••••••••••••••••" echo "• Building package •" echo "••••••••••••••••••••" -echo "• Removing old build..." +echo "• Removing old build from 'data-raw/'..." rm data-raw/AMR_*.tar.gz -echo "• Building to 'data-raw'..." +echo "• Building 'data-raw/AMR_${new_version}.tar.gz'..." Rscript -e "x <- devtools::build(path = 'data-raw', vignettes = FALSE, manual = FALSE, binary = FALSE, quiet = TRUE)" echo "• Installing..." Rscript -e "devtools::install(quiet = TRUE, dependencies = FALSE)" diff --git a/index.md b/index.md index bb2a0324..f8a7871a 100644 --- a/index.md +++ b/index.md @@ -35,6 +35,8 @@ example_isolates %>% select(mo, aminoglycosides(), carbapenems()) #> NOTE: Using column 'mo' as input for mo_is_gram_negative() #> NOTE: Using column 'mo' as input for mo_is_intrinsic_resistant() +#> NOTE: Determining intrinsic resistance based on 'EUCAST Expert Rules' and +#> 'EUCAST Intrinsic Resistance and Unusual Phenotypes' v3.2 from 2020. #> Selecting aminoglycosides: 'AMK' (amikacin), 'GEN' (gentamicin), #> 'KAN' (kanamycin), 'TOB' (tobramycin) #> Selecting carbapenems: 'IPM' (imipenem), 'MEM' (meropenem) @@ -52,6 +54,15 @@ With only having defined a row filter on Gram-negative bacteria with intrinsic r |*Stenotrophomonas maltophilia* | R | R | R | R | R | R | |*Pseudomonas aeruginosa* | S | S | R | S | | S | +A base R equivalent would be: + +```r +example_isolates$mo <- mo_fullname(example_isolates$mo) +example_isolates[which(mo_is_gram_negative() & + mo_is_intrinsic_resistant(ab = "cefotax")), + c("mo", aminoglycosides(), carbapenems())] +``` + #### Partners The development of this package is part of, related to, or made possible by: diff --git a/tests/testthat/test-zzz.R b/tests/testthat/test-zzz.R index 30500af1..c9cffce0 100644 --- a/tests/testthat/test-zzz.R +++ b/tests/testthat/test-zzz.R @@ -29,16 +29,13 @@ test_that("imports work", { skip_on_cran() # Check if these function still exist in the package (all are in Suggests field) - # Since GitHub Action runs every night, we will be emailed when a dependency fails based on this unit test + # Since GitHub Action runs every night, we will get emailed when a dependency fails based on this unit test + + # functions used by import_fn() import_functions <- c( "anti_join" = "dplyr", "cur_column" = "dplyr", - "cur_data" = "dplyr", - "document_position" = "rstudioapi", - "document_range" = "rstudioapi", - "freq.default" = "cleaner", "full_join" = "dplyr", - "getSourceEditorContext" = "rstudioapi", "has_internet" = "curl", "html_attr" = "rvest", "html_children" = "rvest", @@ -46,22 +43,75 @@ test_that("imports work", { "html_nodes" = "rvest", "html_table" = "rvest", "html_text" = "rvest", - "inline_hist" = "skimr", "inner_join" = "dplyr", "insertText" = "rstudioapi", "left_join" = "dplyr", "new_pillar_shaft_simple" = "pillar", - "read_excel" = "readxl", "read_html" = "xml2", "right_join" = "dplyr", "semi_join" = "dplyr", - "sfl" = "skimr", "showQuestion" = "rstudioapi") + # functions that are called directly + call_functions <- c( + # cleaner + "freq.default" = "cleaner", + # skmir + "inline_hist" = "skimr", + "sfl" = "skimr", + # set_mo_source + "read_excel" = "readxl", + # ggplot_rsi + "aes_string" = "ggplot2", + "element_blank" = "ggplot2", + "element_line" = "ggplot2", + "element_text" = "ggplot2", + "facet_wrap" = "ggplot2", + "geom_text" = "ggplot2", + "ggplot" = "ggplot2", + "labs" = "ggplot2", + "layer" = "ggplot2", + "position_fill" = "ggplot2", + "scale_fill_manual" = "ggplot2", + "scale_y_continuous" = "ggplot2", + "theme" = "ggplot2", + "theme_minimal" = "ggplot2", + # ggplot_pca + "aes" = "ggplot2", + "arrow" = "ggplot2", + "element_blank" = "ggplot2", + "element_line" = "ggplot2", + "element_text" = "ggplot2", + "expand_limits" = "ggplot2", + "geom_path" = "ggplot2", + "geom_point" = "ggplot2", + "geom_segment" = "ggplot2", + "geom_text" = "ggplot2", + "ggplot" = "ggplot2", + "labs" = "ggplot2", + "theme" = "ggplot2", + "theme_minimal" = "ggplot2", + "unit" = "ggplot2", + "xlab" = "ggplot2", + "ylab" = "ggplot2", + # resistance_predict + "aes" = "ggplot2", + "geom_errorbar" = "ggplot2", + "geom_point" = "ggplot2", + "geom_ribbon" = "ggplot2", + "ggplot" = "ggplot2", + "labs" = "ggplot2" + ) + + import_functions <- c(import_functions, call_functions) + + # check if all are in Suggests field + expect_true(all(unique(import_functions) %in% strsplit(packageDescription("AMR")$Suggests, ",\n")[[1]])) + for (i in seq_len(length(import_functions))) { fn <- names(import_functions)[i] pkg <- unname(import_functions[i]) expect(!is.null(import_fn(name = fn, pkg = pkg, error_on_fail = FALSE)), - failure_message = paste0("Function ", pkg, "::", fn, "() does not exist")) + failure_message = paste0("Function ", pkg, "::", fn, "() does not exist anymore")) } })