Skip to contents

Functions to plot classes sir, mic and disk, with support for base R and ggplot2.

Especially the scale_*_mic() functions are relevant wrappers to plot MIC values for ggplot2. They allows custom MIC ranges and to plot intermediate log2 levels for missing MIC values.

Usage

scale_x_mic(keep_operators = "edges", mic_range = NULL, ...)

scale_y_mic(keep_operators = "edges", mic_range = NULL, ...)

scale_colour_mic(keep_operators = "edges", mic_range = NULL, ...)

scale_fill_mic(keep_operators = "edges", mic_range = NULL, ...)

scale_x_sir(colours_SIR = c("#3CAEA3", "#F6D55C", "#ED553B"),
  language = get_AMR_locale(), eucast_I = getOption("AMR_guideline",
  "EUCAST") == "EUCAST", ...)

scale_colour_sir(colours_SIR = c("#3CAEA3", "#F6D55C", "#ED553B"),
  language = get_AMR_locale(), eucast_I = getOption("AMR_guideline",
  "EUCAST") == "EUCAST", ...)

scale_fill_sir(colours_SIR = c("#3CAEA3", "#F6D55C", "#ED553B"),
  language = get_AMR_locale(), eucast_I = getOption("AMR_guideline",
  "EUCAST") == "EUCAST", ...)

# S3 method for class 'mic'
plot(x, mo = NULL, ab = NULL,
  guideline = getOption("AMR_guideline", "EUCAST"),
  main = deparse(substitute(x)), ylab = translate_AMR("Frequency", language
  = language),
  xlab = translate_AMR("Minimum Inhibitory Concentration (mg/L)", language =
  language), colours_SIR = c("#3CAEA3", "#F6D55C", "#ED553B"),
  language = get_AMR_locale(), expand = TRUE,
  include_PKPD = getOption("AMR_include_PKPD", TRUE),
  breakpoint_type = getOption("AMR_breakpoint_type", "human"), ...)

# S3 method for class 'mic'
autoplot(object, mo = NULL, ab = NULL,
  guideline = getOption("AMR_guideline", "EUCAST"),
  title = deparse(substitute(object)), ylab = translate_AMR("Frequency",
  language = language),
  xlab = translate_AMR("Minimum Inhibitory Concentration (mg/L)", language =
  language), colours_SIR = c("#3CAEA3", "#F6D55C", "#ED553B"),
  language = get_AMR_locale(), expand = TRUE,
  include_PKPD = getOption("AMR_include_PKPD", TRUE),
  breakpoint_type = getOption("AMR_breakpoint_type", "human"), ...)

# S3 method for class 'disk'
plot(x, main = deparse(substitute(x)),
  ylab = translate_AMR("Frequency", language = language),
  xlab = translate_AMR("Disk diffusion diameter (mm)", language = language),
  mo = NULL, ab = NULL, guideline = getOption("AMR_guideline", "EUCAST"),
  colours_SIR = c("#3CAEA3", "#F6D55C", "#ED553B"),
  language = get_AMR_locale(), expand = TRUE,
  include_PKPD = getOption("AMR_include_PKPD", TRUE),
  breakpoint_type = getOption("AMR_breakpoint_type", "human"), ...)

# S3 method for class 'disk'
autoplot(object, mo = NULL, ab = NULL,
  title = deparse(substitute(object)), ylab = translate_AMR("Frequency",
  language = language), xlab = translate_AMR("Disk diffusion diameter (mm)",
  language = language), guideline = getOption("AMR_guideline", "EUCAST"),
  colours_SIR = c("#3CAEA3", "#F6D55C", "#ED553B"),
  language = get_AMR_locale(), expand = TRUE,
  include_PKPD = getOption("AMR_include_PKPD", TRUE),
  breakpoint_type = getOption("AMR_breakpoint_type", "human"), ...)

# S3 method for class 'sir'
plot(x, ylab = translate_AMR("Percentage", language =
  language), xlab = translate_AMR("Antimicrobial Interpretation", language =
  language), main = deparse(substitute(x)), language = get_AMR_locale(),
  ...)

# S3 method for class 'sir'
autoplot(object, title = deparse(substitute(object)),
  xlab = translate_AMR("Antimicrobial Interpretation", language = language),
  ylab = translate_AMR("Frequency", language = language),
  colours_SIR = c("#3CAEA3", "#F6D55C", "#ED553B"),
  language = get_AMR_locale(), ...)

facet_sir(facet = c("interpretation", "antibiotic"), nrow = NULL)

scale_y_percent(breaks = function(x) seq(0, max(x, na.rm = TRUE), 0.1),
  limits = c(0, NA))

scale_sir_colours(..., aesthetics, colours_SIR = c("#3CAEA3", "#F6D55C",
  "#ED553B"))

theme_sir()

labels_sir_count(position = NULL, x = "antibiotic",
  translate_ab = "name", minimum = 30, language = get_AMR_locale(),
  combine_SI = TRUE, datalabels.size = 3, datalabels.colour = "grey15")

Arguments

keep_operators

a character specifying how to handle operators (such as > and <=) in the input. Accepts one of three values: "all" (or TRUE) to keep all operators, "none" (or FALSE) to remove all operators, or "edges" to keep operators only at both ends of the range.

mic_range

a manual range to limit the MIC values, e.g., mic_range = c(0.001, 32). Use NA to prevent a limit on one side, e.g., mic_range = c(NA, 32).

...

arguments passed on to methods

colours_SIR

colours to use for filling in the bars, must be a vector of three values (in the order S, I and R). The default colours are colour-blind friendly.

language

language to be used to translate 'Susceptible', 'Increased exposure'/'Intermediate' and 'Resistant' - the default is system language (see get_AMR_locale()) and can be overwritten by setting the package option AMR_locale, e.g. options(AMR_locale = "de"), see translate. Use language = NULL to prevent translation.

eucast_I

a logical to indicate whether the 'I' must be interpreted as "Susceptible, under increased exposure". Will be TRUE if the default AMR interpretation guideline is set to EUCAST (which is the default). With FALSE, it will be interpreted as "Intermediate".

x, object

values created with as.mic(), as.disk() or as.sir() (or their random_* variants, such as random_mic())

mo

any (vector of) text that can be coerced to a valid microorganism code with as.mo()

ab

any (vector of) text that can be coerced to a valid antimicrobial drug code with as.ab()

guideline

interpretation guideline to use - the default is the latest included EUCAST guideline, see Details

main, title

title of the plot

xlab, ylab

axis title

expand

a logical to indicate whether the range on the x axis should be expanded between the lowest and highest value. For MIC values, intermediate values will be factors of 2 starting from the highest MIC value. For disk diameters, the whole diameter range will be filled.

include_PKPD

a logical to indicate that PK/PD clinical breakpoints must be applied as a last resort - the default is TRUE. Can also be set with the package option AMR_include_PKPD.

breakpoint_type

the type of breakpoints to use, either "ECOFF", "animal", or "human". ECOFF stands for Epidemiological Cut-Off values. The default is "human", which can also be set with the package option AMR_breakpoint_type. If host is set to values of veterinary species, this will automatically be set to "animal".

facet

variable to split plots by, either "interpretation" (default) or "antibiotic" or a grouping variable

nrow

(when using facet) number of rows

breaks

a numeric vector of positions

limits

a numeric vector of length two providing limits of the scale, use NA to refer to the existing minimum or maximum

aesthetics

aesthetics to apply the colours to - the default is "fill" but can also be (a combination of) "alpha", "colour", "fill", "linetype", "shape" or "size"

position

position adjustment of bars, either "fill", "stack" or "dodge"

translate_ab

a column name of the antibiotics data set to translate the antibiotic abbreviations to, using ab_property()

minimum

the minimum allowed number of available (tested) isolates. Any isolate count lower than minimum will return NA with a warning. The default number of 30 isolates is advised by the Clinical and Laboratory Standards Institute (CLSI) as best practice, see Source.

combine_SI

a logical to indicate whether all values of S, SDD, and I must be merged into one, so the output only consists of S+SDD+I vs. R (susceptible vs. resistant) - the default is TRUE

datalabels.size

size of the datalabels

datalabels.colour

colour of the datalabels

Value

The autoplot() functions return a ggplot model that is extendible with any ggplot2 function.

Details

The scale_*_mic() Functions

The functions scale_x_mic(), scale_y_mic(), scale_colour_mic(), and scale_fill_mic() functions allow to plot the mic class (MIC values) on a continuous, logarithmic scale. They also allow to rescale the MIC range with an 'inside' or 'outside' range if required, and retain the signs in MIC values if desired. Missing intermediate log2 levels will be plotted too.

The scale_*_sir() Functions

The functions scale_x_sir(), scale_colour_sir(), and scale_fill_sir() functions allow to plot the sir class in the right order (S < SDD < I < R < NI). At default, they translate the S/I/R values to an interpretative text ("Susceptible", "Resistant", etc.) in any of the 20 supported languages (use language = NULL to keep S/I/R). Also, except for scale_x_sir(), they set colour-blind friendly colours to the colour and fill aesthetics.

Additional ggplot2 Functions

This package contains more functions that extend the ggplot2 package, to help in visualising AMR data results. All these functions are internally used by ggplot_sir() too.

  • facet_sir() creates 2d plots (at default based on S/I/R) using ggplot2::facet_wrap().

  • scale_y_percent() transforms the y axis to a 0 to 100% range using ggplot2::scale_y_continuous().

  • scale_sir_colours() allows to set colours to any aesthetic, even for shape or linetype.

  • theme_sir() is a [ggplot2 theme][ggplot2::theme() with minimal distraction.

  • labels_sir_count() print datalabels on the bars with percentage and number of isolates, using ggplot2::geom_text().

The interpretation of "I" will be named "Increased exposure" for all EUCAST guidelines since 2019, and will be named "Intermediate" in all other cases.

For interpreting MIC values as well as disk diffusion diameters, the default guideline is EUCAST 2024, unless the package option AMR_guideline is set. See as.sir() for more information.

Examples

some_mic_values <- random_mic(size = 100)
some_disk_values <- random_disk(size = 100, mo = "Escherichia coli", ab = "cipro")
some_sir_values <- random_sir(50, prob_SIR = c(0.55, 0.05, 0.30))


# Plotting using base R's plot() ---------------------------------------

plot(some_mic_values)

plot(some_disk_values)

plot(some_sir_values)


# when providing the microorganism and antibiotic, colours will show interpretations:
plot(some_mic_values, mo = "S. aureus", ab = "ampicillin")

plot(some_disk_values, mo = "Escherichia coli", ab = "cipro")

plot(some_disk_values, mo = "Escherichia coli", ab = "cipro", language = "nl")



# Plotting using scale_x_mic() -----------------------------------------
# \donttest{
if (require("ggplot2")) {
  mic_plot <- ggplot(data.frame(mics = as.mic(c(0.25, "<=4", 4, 8, 32, ">=32")),
                                counts = c(1, 1, 2, 2, 3, 3)),
                     aes(mics, counts)) +
    geom_col()
  mic_plot +
    labs(title = "without scale_x_mic()")
}

if (require("ggplot2")) {
  mic_plot +
    scale_x_mic() +
    labs(title = "with scale_x_mic()")
}
#> Error in if (!is.na(mic_range[1]) && mic_range[1] < lims[1]) {    lims[1] <- mic_range[1]}: missing value where TRUE/FALSE needed
if (require("ggplot2")) {
  mic_plot +
    scale_x_mic(keep_operators = "all") +
    labs(title = "with scale_x_mic() keeping all operators")
}
#> Error in if (!is.na(mic_range[1]) && mic_range[1] < lims[1]) {    lims[1] <- mic_range[1]}: missing value where TRUE/FALSE needed
if (require("ggplot2")) {
  mic_plot +
    scale_x_mic(mic_range = c(1, 16)) +
    labs(title = "with scale_x_mic() using a manual 'within' range")
}

if (require("ggplot2")) {
  mic_plot +
    scale_x_mic(mic_range = c(0.032, 256)) +
    labs(title = "with scale_x_mic() using a manual 'outside' range")
}



# Plotting using scale_y_mic() -----------------------------------------
some_groups <- sample(LETTERS[1:5], 20, replace = TRUE)

if (require("ggplot2")) {
  ggplot(data.frame(mic = some_mic_values,
                    group = some_groups),
         aes(group, mic)) +
    geom_boxplot() +
    geom_violin(linetype = 2, colour = "grey", fill = NA) +
    scale_y_mic()
}
#> Error in if (!is.na(mic_range[1]) && mic_range[1] < lims[1]) {    lims[1] <- mic_range[1]}: missing value where TRUE/FALSE needed
if (require("ggplot2")) {
  ggplot(data.frame(mic = some_mic_values,
                    group = some_groups),
         aes(group, mic)) +
    geom_boxplot() +
    geom_violin(linetype = 2, colour = "grey", fill = NA) +
    scale_y_mic(mic_range = c(NA, 2))
}



# Plotting using scale_fill_mic() -----------------------------------------
some_counts <- as.integer(runif(20, 5, 50))

if (require("ggplot2")) {
  ggplot(data.frame(mic = some_mic_values,
                   group = some_groups,
                   counts = some_counts),
         aes(group, counts, fill = mic)) +
    geom_col() +
    scale_fill_mic(mic_range = c(0.5, 16))
}


# Plotting using scale_x_sir() -----------------------------------------
if (require("ggplot2")) {
  ggplot(data.frame(x = c("I", "R", "S"),
                    y = c(45,323, 573)),
         aes(x, y)) +
    geom_col() +
    scale_x_sir()
}



# Plotting using scale_y_mic() and scale_colour_sir() ------------------
if (require("ggplot2")) {
  plain <- ggplot(data.frame(mic = some_mic_values,
                             group = some_groups,
                             sir = as.sir(some_mic_values,
                                          mo = "E. coli",
                                          ab = "cipro")),
                  aes(x = group, y = mic, colour = sir)) +
    theme_minimal() +
    geom_boxplot(fill = NA, colour = "grey") +
    geom_jitter(width = 0.25)
  
  plain
}
#> 
#> ℹ Run sir_interpretation_history() afterwards to retrieve a logbook with
#>   all the details of the breakpoint interpretations.
#> 
#> Interpreting MIC values: 'cipro' (CIP, ciprofloxacin), EUCAST 2024...
#>  NOTE 
#>   • Multiple breakpoints available for ciprofloxacin (CIP) in Escherichia coli - assuming body site 'Non-meningitis'.

if (require("ggplot2")) {
  # and now with our MIC and SIR scale functions:
  plain +
    scale_y_mic() +
    scale_colour_sir()
}
#> Error in if (!is.na(mic_range[1]) && mic_range[1] < lims[1]) {    lims[1] <- mic_range[1]}: missing value where TRUE/FALSE needed
if (require("ggplot2")) {
  plain +
    scale_y_mic(mic_range = c(0.005, 32), name = "Our MICs!") +
    scale_colour_sir(language = "nl", eucast_I = FALSE,
                     name = "In Dutch!")
}



# Plotting using ggplot2's autoplot() ----------------------------------
if (require("ggplot2")) {
  autoplot(some_mic_values)
}

if (require("ggplot2")) {
  autoplot(some_disk_values, mo = "Escherichia coli", ab = "cipro")
}

if (require("ggplot2")) {
  autoplot(some_sir_values)
}



# Plotting using scale_y_percent() -------------------------------------
if (require("ggplot2")) {
  p <- ggplot(data.frame(mics = as.mic(c(0.25, "<=4", 4, 8, 32, ">=32")),
                               counts = c(1, 1, 2, 2, 3, 3)),
                         aes(mics, counts / sum(counts))) +
    geom_col()
  print(p)
  
  p2 <- p +
    scale_y_percent() +
    theme_sir()
  print(p2)
  
  p +
    scale_y_percent(breaks = seq(from = 0, to = 1, by = 0.1),
                    limits = c(0, 1)) +
    theme_sir()
}



# }