diff --git a/.github/workflows/codecovr.yaml b/.github/workflows/codecovr.yaml index e1e19c7d..571a93c1 100644 --- a/.github/workflows/codecovr.yaml +++ b/.github/workflows/codecovr.yaml @@ -31,10 +31,10 @@ on: branches: - master -name: code-tested +name: code-coverage jobs: - code-tested: + code-coverage: runs-on: macOS-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} diff --git a/DESCRIPTION b/DESCRIPTION index 788d7664..ef2ab328 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: AMR -Version: 1.5.0.9012 -Date: 2021-01-25 +Version: 1.5.0.9013 +Date: 2021-01-28 Title: Antimicrobial Resistance Analysis Authors@R: c( person(role = c("aut", "cre"), diff --git a/NAMESPACE b/NAMESPACE index 5caeab7e..aab403a5 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -60,12 +60,14 @@ S3method(print,mic) S3method(print,mo) S3method(print,mo_renamed) S3method(print,mo_uncertainties) +S3method(print,pca) S3method(print,rsi) S3method(skewness,data.frame) S3method(skewness,default) S3method(skewness,matrix) S3method(summary,mic) S3method(summary,mo) +S3method(summary,pca) S3method(summary,rsi) S3method(unique,ab) S3method(unique,disk) diff --git a/NEWS.md b/NEWS.md index 4ae399b0..a8ebedc9 100755 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,5 @@ -# AMR 1.5.0.9012 -## Last updated: 25 January 2021 +# AMR 1.5.0.9013 +## Last updated: 28 January 2021 ### New * Support for EUCAST Clinical Breakpoints v11.0 (2021), effective in the `eucast_rules()` function and in `as.rsi()` to interpret MIC and disk diffusion values. This is now the default guideline in this package. @@ -36,6 +36,9 @@ * `is.rsi.eligible()` now returns `FALSE` immediately if the input does not contain any of the values "R", "S" or "I". This drastically improves speed, also for a lot of other functions that rely on automatic determination of antibiotic columns. * Functions `get_episode()` and `is_new_episode()` now support less than a day as value for argument `episode_days` (e.g., to include one patient/test per hour) * Argument `ampc_cephalosporin_resistance` in `eucast_rules()` now also applies to value "I" (not only "S") +* Updated colours of values R, S and I in tibble printing +* Functions `print()` and `summary()` on a Principal Components Analysis object (`pca()`) now print additional group info if the original data was grouped using `dplyr::group_by()` + ### Other * Big documentation updates diff --git a/R/aa_helper_functions.R b/R/aa_helper_functions.R index 8b9ecb60..b405680b 100755 --- a/R/aa_helper_functions.R +++ b/R/aa_helper_functions.R @@ -802,13 +802,13 @@ font_green_bg <- function(..., collapse = " ") { try_colour(..., before = "\033[42m", after = "\033[49m", collapse = collapse) } font_rsi_R_bg <- function(..., collapse = " ") { - try_colour(..., before = "\033[48;5;202m", after = "\033[49m", collapse = collapse) + try_colour(..., before = "\033[48;5;210m", after = "\033[49m", collapse = collapse) } font_rsi_S_bg <- function(..., collapse = " ") { - try_colour(..., before = "\033[48;5;76m", after = "\033[49m", collapse = collapse) + try_colour(..., before = "\033[48;5;113m", after = "\033[49m", collapse = collapse) } font_rsi_I_bg <- function(..., collapse = " ") { - try_colour(..., before = "\033[48;5;148m", after = "\033[49m", collapse = collapse) + try_colour(..., before = "\033[48;5;185m", after = "\033[49m", collapse = collapse) } font_red_bg <- function(..., collapse = " ") { try_colour(..., before = "\033[41m", after = "\033[49m", collapse = collapse) diff --git a/R/ab_class_selectors.R b/R/ab_class_selectors.R index 81b2e005..f0226178 100644 --- a/R/ab_class_selectors.R +++ b/R/ab_class_selectors.R @@ -25,7 +25,7 @@ #' Antibiotic Class Selectors #' -#' These functions help to select the columns of antibiotics that are of a specific antibiotic class, without the need to define the columns or antibiotic abbreviations. +#' These functions help to select the columns of antibiotics that are of a specific antibiotic class, without the need to define the columns or antibiotic abbreviations. \strong{\Sexpr{ifelse(as.double(R.Version()$major) + (as.double(R.Version()$minor) / 10) < 3.2, paste0("NOTE: THESE FUNCTIONS DO NOT WORK ON YOUR CURRENT R VERSION. These functions require R version 3.2 or later - you have ", R.version.string, "."), "")}} #' @inheritSection lifecycle Stable Lifecycle #' @inheritParams filter_ab_class #' @details \strong{\Sexpr{ifelse(as.double(R.Version()$major) + (as.double(R.Version()$minor) / 10) < 3.2, paste0("NOTE: THESE FUNCTIONS DO NOT WORK ON YOUR CURRENT R VERSION. These functions require R version 3.2 or later - you have ", R.version.string, "."), "")}} diff --git a/R/mo.R b/R/mo.R index 9b732809..3af64393 100755 --- a/R/mo.R +++ b/R/mo.R @@ -2018,7 +2018,7 @@ repair_reference_df <- function(reference_df) { } strip_words <- function(text, n, side = "right") { - out <- lapply(strsplit(x, " "), function(x) { + out <- lapply(strsplit(text, " "), function(x) { if (side %like% "^r" & length(x) > n) { x[seq_len(length(x) - n)] } else if (side %like% "^l" & length(x) > n) { diff --git a/R/pca.R b/R/pca.R index 46f8f957..41b0cecb 100755 --- a/R/pca.R +++ b/R/pca.R @@ -47,7 +47,7 @@ #' # calculate the resistance per group first #' resistance_data <- example_isolates %>% #' group_by(order = mo_order(mo), # group on anything, like order -#' genus = mo_genus(mo)) %>% # and genus as we do here +#' genus = mo_genus(mo)) %>% # and genus as we do here; #' summarise_if(is.rsi, resistance) # then get resistance of all drugs #' #' # now conduct PCA for certain antimicrobial agents @@ -99,7 +99,7 @@ pca <- function(x, x <- as.data.frame(new_list, stringsAsFactors = FALSE) if (any(vapply(FUN.VALUE = logical(1), x, function(y) !is.numeric(y)))) { - warning_("Be sure to first calculate the resistance (or susceptibility) of variables with antimicrobial test results, since PCA works with numeric variables only. See Examples in ?pca.") + warning_("Be sure to first calculate the resistance (or susceptibility) of variables with antimicrobial test results, since PCA works with numeric variables only. See Examples in ?pca.", call = FALSE) } # set column names @@ -117,11 +117,51 @@ pca <- function(x, pca_data <- x[, which(vapply(FUN.VALUE = logical(1), x, function(x) is.numeric(x)))] - message_("Columns selected for PCA: ", paste0(font_bold(colnames(pca_data)), collapse = "/"), + message_("Columns selected for PCA: ", vector_or(font_bold(colnames(pca_data), collapse = NULL), + quotes = "'", + last_sep = " and "), ". Total observations available: ", nrow(pca_data), ".") - pca_model <- prcomp(pca_data, retx = retx, center = center, scale. = scale., tol = tol, rank. = rank.) - attr(pca_model, "non_numeric_cols") <- x[, vapply(FUN.VALUE = logical(1), x, function(y) !is.numeric(y) & !all(is.na(y))), drop = FALSE] + if (as.double(R.Version()$major) + (as.double(R.Version()$minor) / 10) < 3.4) { + # stats::prcomp prior to 3.4.0 does not have the 'rank.' argument + pca_model <- prcomp(pca_data, retx = retx, center = center, scale. = scale., tol = tol) + } else { + pca_model <- prcomp(pca_data, retx = retx, center = center, scale. = scale., tol = tol, rank. = rank.) + } + groups <- x[, vapply(FUN.VALUE = logical(1), x, function(y) !is.numeric(y) & !all(is.na(y))), drop = FALSE] + rownames(groups) <- NULL + attr(pca_model, "non_numeric_cols") <- groups class(pca_model) <- c("pca", class(pca_model)) pca_model } + +#' @method print pca +#' @export +#' @noRd +print.pca <- function(x, ...) { + a <- attributes(x)$non_numeric_cols + if (!is.null(a)) { + print_pca_group(a) + class(x) <- class(x)[class(x) != "pca"] + } + print(x, ...) +} + +#' @method summary pca +#' @export +#' @noRd +summary.pca <- function(object, ...) { + a <- attributes(object)$non_numeric_cols + if (!is.null(a)) { + print_pca_group(a) + class(object) <- class(object)[class(object) != "pca"] + } + summary(object, ...) +} + +print_pca_group <- function(a) { + grps <- sort(unique(a[, 1, drop = TRUE])) + cat("Groups (n=", length(grps), ", named as '", colnames(a)[1], "'):\n", sep = "") + print(grps) + cat("\n") +} diff --git a/R/rsi.R b/R/rsi.R index c8210e58..16f050f6 100755 --- a/R/rsi.R +++ b/R/rsi.R @@ -848,10 +848,14 @@ exec_as.rsi <- function(method, # will be exported using s3_register() in R/zzz.R pillar_shaft.rsi <- function(x, ...) { out <- trimws(format(x)) - out[is.na(x)] <- font_grey(" NA") - out[x == "R"] <- font_rsi_R_bg(font_black(" R ")) - out[x == "S"] <- font_rsi_S_bg(font_black(" S ")) - out[x == "I"] <- font_rsi_I_bg(font_black(" I ")) + if (has_colour()) { + # colours will anyway not work when has_colour() == FALSE, + # but then the indentation should also not be applied + out[is.na(x)] <- font_grey(" NA") + out[x == "R"] <- font_rsi_R_bg(font_black(" R ")) + out[x == "S"] <- font_rsi_S_bg(font_black(" S ")) + out[x == "I"] <- font_rsi_I_bg(font_black(" I ")) + } create_pillar_column(out, align = "left", width = 5) } diff --git a/data-raw/AMR_1.5.0.9012.tar.gz b/data-raw/AMR_1.5.0.9013.tar.gz similarity index 86% rename from data-raw/AMR_1.5.0.9012.tar.gz rename to data-raw/AMR_1.5.0.9013.tar.gz index 0bbc2b90..edcf021a 100644 Binary files a/data-raw/AMR_1.5.0.9012.tar.gz and b/data-raw/AMR_1.5.0.9013.tar.gz differ diff --git a/docs/404.html b/docs/404.html index 003f6c58..0f1ac301 100644 --- a/docs/404.html +++ b/docs/404.html @@ -81,7 +81,7 @@ AMR (for R) - 1.5.0.9012 + 1.5.0.9013 diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index c85d7dbc..cc03837b 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -81,7 +81,7 @@ AMR (for R) - 1.5.0.9012 + 1.5.0.9013 diff --git a/docs/articles/MDR.html b/docs/articles/MDR.html index 7591faed..36cd6893 100644 --- a/docs/articles/MDR.html +++ b/docs/articles/MDR.html @@ -39,7 +39,7 @@ AMR (for R) - 1.5.0.9010 + 1.5.0.9013 @@ -339,19 +339,19 @@ Unique: 2

 head(my_TB_data)
 #   rifampicin isoniazid gatifloxacin ethambutol pyrazinamide moxifloxacin
-# 1          I         R            I          R            I            I
-# 2          R         R            I          S            R            I
-# 3          I         S            S          I            S            I
-# 4          I         I            R          S            R            I
-# 5          I         R            I          S            S            I
-# 6          S         I            I          I            R            R
+# 1          R         I            I          R            R            R
+# 2          R         S            I          S            R            S
+# 3          R         R            S          S            R            I
+# 4          S         R            R          S            S            R
+# 5          I         R            R          R            R            S
+# 6          I         I            I          R            S            I
 #   kanamycin
 # 1         I
-# 2         R
+# 2         S
 # 3         S
-# 4         R
-# 5         S
-# 6         I
+# 4 S +# 5 R +# 6 R

We can now add the interpretation of MDR-TB to our data set. You can use:

 mdro(my_TB_data, guideline = "TB")
@@ -382,40 +382,40 @@ Unique: 5

1 Mono-resistant -3228 -64.56% -3228 -64.56% +3163 +63.26% +3163 +63.26% 2 Negative -1017 -20.34% -4245 -84.90% +1009 +20.18% +4172 +83.44% 3 Multi-drug-resistant -421 -8.42% -4666 -93.32% +466 +9.32% +4638 +92.76% 4 Poly-resistant -231 -4.62% -4897 -97.94% +255 +5.10% +4893 +97.86% 5 Extensively drug-resistant -103 -2.06% +107 +2.14% 5000 100.00% diff --git a/docs/articles/SPSS.html b/docs/articles/SPSS.html index f9183cac..0f597de8 100644 --- a/docs/articles/SPSS.html +++ b/docs/articles/SPSS.html @@ -39,7 +39,7 @@ AMR (for R) - 1.5.0.9010 + 1.5.0.9013 @@ -193,7 +193,7 @@

How to import data from SPSS / SAS / Stata

Matthijs S. Berends

-

24 January 2021

+

28 January 2021

Source: vignettes/SPSS.Rmd @@ -256,11 +256,11 @@ # Class <mic> # [1] <NA> -# the Gram stain is avaiable for all bacteria: +# the Gram stain is available for all bacteria: mo_gramstain("E. coli") # [1] "Gram-negative" -# Klebsiella is intrinsic resistant to amoxicllin, according to EUCAST: +# Klebsiella is intrinsic resistant to amoxicillin, according to EUCAST: klebsiella_test <- data.frame(mo = "klebsiella", amox = "S", stringsAsFactors = FALSE) diff --git a/docs/articles/index.html b/docs/articles/index.html index 7507c279..b659123a 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -81,7 +81,7 @@ AMR (for R) - 1.5.0.9012 + 1.5.0.9013 diff --git a/docs/authors.html b/docs/authors.html index 72ab23bb..55827897 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -81,7 +81,7 @@ AMR (for R) - 1.5.0.9012 + 1.5.0.9013 diff --git a/docs/countries.png b/docs/countries.png index 587eec03..f9136554 100644 Binary files a/docs/countries.png and b/docs/countries.png differ diff --git a/docs/countries_large.png b/docs/countries_large.png index b9ee0ea5..2e02aa32 100644 Binary files a/docs/countries_large.png and b/docs/countries_large.png differ diff --git a/docs/index.html b/docs/index.html index a589bb57..aae4c620 100644 --- a/docs/index.html +++ b/docs/index.html @@ -43,7 +43,7 @@ AMR (for R) - 1.5.0.9012 + 1.5.0.9013 @@ -211,7 +211,7 @@ Since you are one of our users, we would like to know how you use the package an

This package is fully independent of any other R package and works on Windows, macOS and Linux with all versions of R since R-3.0.0 (April 2013). It was designed to work in any setting, including those with very limited resources. It was created for both routine data analysis and academic research at the Faculty of Medical Sciences of the University of Groningen, in collaboration with non-profit organisations Certe Medical Diagnostics and Advice and University Medical Center Groningen. This R package is actively maintained and is free software (see Copyright).

- Used in 138 countries
Since its first public release in early 2018, this package has been downloaded from 138 countries. Click the map to enlarge and to see the country names. + Used in 148 countries
Since its first public release in early 2018, this package has been downloaded from 148 countries. Click the map to enlarge and to see the country names.

@@ -337,7 +337,7 @@ Since you are one of our users, we would like to know how you use the package an -

A base R equivalent would be:

+

A base R equivalent would be, giving the exact same results:

 example_isolates$bacteria <- mo_fullname(example_isolates$mo)
 example_isolates[which(mo_is_gram_negative() &
diff --git a/docs/news/index.html b/docs/news/index.html
index 8cc42558..cf3cddf5 100644
--- a/docs/news/index.html
+++ b/docs/news/index.html
@@ -81,7 +81,7 @@
       
       
         AMR (for R)
-        1.5.0.9012
+        1.5.0.9013
       
     
@@ -236,13 +236,13 @@ Source: NEWS.md
-
-

-AMR 1.5.0.9012 Unreleased +
+

+AMR 1.5.0.9013 Unreleased

-
+

-Last updated: 25 January 2021 +Last updated: 28 January 2021

@@ -290,6 +290,9 @@ is.rsi.eligible() now returns FALSE immediately if the input does not contain any of the values “R”, “S” or “I”. This drastically improves speed, also for a lot of other functions that rely on automatic determination of antibiotic columns.
  • Functions get_episode() and is_new_episode() now support less than a day as value for argument episode_days (e.g., to include one patient/test per hour)
  • Argument ampc_cephalosporin_resistance in eucast_rules() now also applies to value “I” (not only “S”)
  • +
  • Updated colours of values R, S and I in tibble printing
  • +
  • Functions print() and summary() on a Principal Components Analysis object (pca()) now print additional group info if the original data was grouped using dplyr::group_by() +
  • @@ -616,7 +619,7 @@

    Making this package independent of especially the tidyverse (e.g. packages dplyr and tidyr) tremendously increases sustainability on the long term, since tidyverse functions change quite often. Good for users, but hard for package maintainers. Most of our functions are replaced with versions that only rely on base R, which keeps this package fully functional for many years to come, without requiring a lot of maintenance to keep up with other packages anymore. Another upside it that this package can now be used with all versions of R since R-3.0.0 (April 2013). Our package is being used in settings where the resources are very limited. Fewer dependencies on newer software is helpful for such settings.

    Negative effects of this change are:

      -
    • Function freq() that was borrowed from the cleaner package was removed. Use cleaner::freq(), or run library("cleaner") before you use freq().
    • +
    • Function freq() that was borrowed from the cleaner package was removed. Use cleaner::freq(), or run library("cleaner") before you use freq().
    • Printing values of class mo or rsi in a tibble will no longer be in colour and printing rsi in a tibble will show the class <ord>, not <rsi> anymore. This is purely a visual effect.
    • All functions from the mo_* family (like mo_name() and mo_gramstain()) are noticeably slower when running on hundreds of thousands of rows.
    • For developers: classes mo and ab now both also inherit class character, to support any data transformation. This change invalidates code that checks for class length == 1.
    • @@ -953,7 +956,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/ #> invalid microorganism code, NA generated

    This is important, because a value like "testvalue" could never be understood by e.g. mo_name(), although the class would suggest a valid microbial code.

    -
  • Function freq() has moved to a new package, clean (CRAN link), since creating frequency tables actually does not fit the scope of this package. The freq() function still works, since it is re-exported from the clean package (which will be installed automatically upon updating this AMR package).

  • +
  • Function freq() has moved to a new package, clean (CRAN link), since creating frequency tables actually does not fit the scope of this package. The freq() function still works, since it is re-exported from the clean package (which will be installed automatically upon updating this AMR package).

  • Renamed data set septic_patients to example_isolates

  • @@ -1222,7 +1225,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
  • The age() function gained a new argument exact to determine ages with decimals
  • Removed deprecated functions guess_mo(), guess_atc(), EUCAST_rules(), interpretive_reading(), rsi()
  • -
  • Frequency tables (freq()): +
  • Frequency tables (freq()):
    • speed improvement for microbial IDs

    • fixed factor level names for R Markdown

    • @@ -1232,12 +1235,12 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
       
       septic_patients %>% 
      -  freq(age) %>% 
      +  freq(age) %>% 
         boxplot()
       # grouped boxplots:
       septic_patients %>% 
         group_by(hospital_id) %>% 
      -  freq(age) %>%
      +  freq(age) %>%
         boxplot()
    @@ -1247,7 +1250,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
  • Added ceftazidim intrinsic resistance to Streptococci
  • Changed default settings for age_groups(), to let groups of fives and tens end with 100+ instead of 120+
  • -
  • Fix for freq() for when all values are NA +
  • Fix for freq() for when all values are NA
  • Fix for first_isolate() for when dates are missing
  • Improved speed of guess_ab_col() @@ -1488,7 +1491,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
  • -
  • Frequency tables (freq() function): +
  • Frequency tables (freq() function):
    • Support for tidyverse quasiquotation! Now you can create frequency tables of function outcomes:

      @@ -1498,15 +1501,15 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/ # OLD WAY septic_patients %>% mutate(genus = mo_genus(mo)) %>% - freq(genus) + freq(genus) # NEW WAY septic_patients %>% - freq(mo_genus(mo)) + freq(mo_genus(mo)) # Even supports grouping variables: septic_patients %>% group_by(gender) %>% - freq(mo_genus(mo))
  • + freq(mo_genus(mo))
  • Header info is now available as a list, with the header function

  • The argument header is now set to TRUE at default, even for markdown

  • @@ -1589,7 +1592,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
  • Using portion_* functions now throws a warning when total available isolate is below argument minimum

  • Functions as.mo, as.rsi, as.mic, as.atc and freq will not set package name as attribute anymore

  • -

    Frequency tables - freq():

    +

    Frequency tables - freq():

    • Support for grouping variables, test with:

      @@ -1597,14 +1600,14 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/ septic_patients %>% group_by(hospital_id) %>% - freq(gender)
  • + freq(gender)
  • Support for (un)selecting columns:

     
     septic_patients %>% 
    -  freq(hospital_id) %>% 
    +  freq(hospital_id) %>% 
       select(-count, -cum_count) # only get item, percent, cum_percent
  • Check for hms::is.hms

  • @@ -1622,7 +1625,7 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
  • Removed diacritics from all authors (columns microorganisms$ref and microorganisms.old$ref) to comply with CRAN policy to only allow ASCII characters

  • Fix for mo_property not working properly

  • Fix for eucast_rules where some Streptococci would become ceftazidime R in EUCAST rule 4.5

  • -
  • Support for named vectors of class mo, useful for top_freq()

  • +
  • Support for named vectors of class mo, useful for top_freq()

  • ggplot_rsi and scale_y_percent have breaks argument

  • AI improvements for as.mo:

    @@ -1790,13 +1793,13 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/
     
     my_matrix = with(septic_patients, matrix(c(age, gender), ncol = 2))
    -freq(my_matrix)
    +freq(my_matrix)

    For lists, subsetting is possible:

     
     my_list = list(age = septic_patients$age, gender = septic_patients$gender)
    -my_list %>% freq(age)
    -my_list %>% freq(gender)
    +my_list %>% freq(age) +my_list %>% freq(gender)
  • @@ -1870,13 +1873,13 @@ This works for all drug combinations, such as ampicillin/sulbactam, ceftazidime/