Skip to contents

While visual inspection is probably the most reliable way of identifying anomalies in time series, things can be missed when there are large numbers of time series to inspect. In this case, it can be useful to additionally test the individual time series for certain conditions, such as the presence of missing values or for values breaching pre-set limits, and to alert the user to them.

The alert results are displayed in different ways depending on the chosen type of output. Tabs containing time series which failed at least one alert are highlighted. A separate tab containing all the alert results is added at the end.

It is also possible to just generate the alert results as a data frame.

Note: This functionality is still in the early stages of development, and can increase the document size and rendering time of the report considerably.

Overview

One or more alerting rules can be specified within an alert_rules() object, which is then passed into the alert_rules parameter. When creating a standard mantis report, the alertspec parameter also controls how the results are displayed in the final tab.

Built-in rules

There are a number of built-in rules that can be used to test for simple conditions, the simplest of which is testing for the presence of missing values. The extent_type and extent_value parameters can be used to adjust the tolerance. E.g.

# alert if all values are NA
ars <- alert_rules(alert_missing(extent_type = "all"))

# alert if there are 10 or more missing values in total
# or if the last 3 or more values are missing
# or if 5 or more values in a row are missing
ars <- alert_rules(
  alert_missing(extent_type = "any", extent_value = 10),
  alert_missing(extent_type = "last", extent_value = 3),
  alert_missing(extent_type = "consecutive", extent_value = 5)
)

The alert_equals(), alert_below(), alert_above() rules work similarly, but with an extra parameter rule_value to compare against. It is also possible to compare a range of values with another range of values using the alert_difference_above_perc() and alert_difference_below_perc() rules. This can be useful for checking if recent values are lower/higher than in a previous period, over a particular percentage. This comparison is based on the mean of values in the two periods. The ranges should be contiguous, and denote positions from the end of the time series. E.g.

# alert if the mean of last 3 values is more than 20% higher than
# the mean of the preceding 12 values
ars <- alert_rules(
  alert_difference_above_perc(
    current_period = 1:3,
    previous_period = 4:15,
    rule_value = 20
  )
)

Custom rules

If you want to apply a more complex rule, you can specify your own using alert_custom(). E.g.

ars <- alert_rules(
  alert_custom(
    short_name = "my_rule_combo",
    description = "Over 3 missing values and max value is > 10",
    function_call = quote(
      sum(is.na(value)) > 3 && max(value, na.rm = TRUE) > 10
    )
  ),
  alert_custom(
    short_name = "my_rule_doubled",
    description = "Last value is over double the first value",
    function_call = quote(
      rev(value)[1] > 2 * value[1]
    )
  )
)

The function_call is evaluated per time series, and the expression inside quote() must return either TRUE or FALSE. A return value of TRUE means the alert result is “FAIL”

Column names that can be used explicitly in the expression are value and timepoint, and which refer to the values in the value_col and timepoint_col columns of the data respectively. Before evaluating the function_call, the dataframe is grouped by the item_col and ordered by the timepoint_col.

Applying different rules to different time series

By default, the specified rules will be run on all time series in the supplied dataframe. You can specify different sets of rules for different time series by using the items parameter, and providing it a named list of character vectors corresponding to the item_cols columns and values that the particular rule should be applied to.

Walkthrough

Generate an interactive mantis report for the example_prescription_numbers dataset supplied with the mantis package.

library(mantis)

data("example_prescription_numbers")
mantis_report(
  df = example_prescription_numbers,
  inputspec = inputspec(
    timepoint_col = "PrescriptionDate",
    item_cols = c("Antibiotic", "Spectrum", "Location"),
    value_col = "NumberOfPrescriptions",
    tab_col = "Location"
  ),
  outputspec = outputspec_interactive(
    sync_axis_range = FALSE
  ),
  report_title = "mantis report",
  dataset_description = "Antibiotic prescriptions by site",
  save_filename = "example_prescription_numbers_interactive",
  show_progress = TRUE
)

In the SITE1 tab, the Vancomycin time series contains a block of NA values but it is not easy to distinguish between NA values and zero values unless you zoom in on the plot (by selecting a section of it with the mouse) or hover the mouse over the relevant time points and read the tooltips.

We can easily add a rule to test for any missing values. While we’re here, we will also add a custom rule to try to catch the fact that Coamoxiclav prescriptions have become much higher than they were at the start.

ars <- alert_rules(
  alert_missing(extent_type = "any", extent_value = 1),
  alert_custom(
    short_name = "my_rule_doubled",
    description = "Last 7 values are over double the first 7 values",
    function_call = quote(
      mean(rev(value)[1:7], na.rm = TRUE) > 2 * (mean(value[1:7], na.rm = TRUE))
    )
  )
)

# create a new report
mantis_report(
  df = example_prescription_numbers,
  inputspec = inputspec(
    timepoint_col = "PrescriptionDate",
    item_cols = c("Antibiotic", "Spectrum", "Location"),
    value_col = "NumberOfPrescriptions",
    tab_col = "Location"
  ),
  outputspec = outputspec_interactive(
    sync_axis_range = FALSE
  ),
  alertspec = alertspec(
    alert_rules = ars,
    show_tab_results = c("FAIL", "NA")
  ),
  report_title = "mantis report with alerts",
  dataset_description = "Antibiotic prescriptions by site",
  save_filename = "example_prescription_numbers_interactive_alerts",
  show_progress = TRUE
)

The report now includes a column for the alert results, and details can be seen by clicking on the triangles. The tab labels will include an exclamation mark if any items in that tab have failed an alert rule.

An additional tab is also created, which lists the alert results. In this example we have decided to exclude any alerts that have passed.

If for some reason we only wanted to apply the custom rule to broad spectrum antibiotics, we can indicate this using the items parameter of the rule.

ars_restricted <- alert_rules(
  alert_missing(extent_type = "any", extent_value = 1),
  alert_custom(
    short_name = "my_rule_doubled",
    description = "Last 7 values are over double the first 7 values",
    function_call = quote(
      mean(rev(value)[1:7], na.rm = TRUE) > 2 * (mean(value[1:7], na.rm = TRUE))
    ),
    items = list("Spectrum" = c("Broad"))
  )
)

# create a new report
mantis_report(
  df = example_prescription_numbers,
  inputspec = inputspec(
    timepoint_col = "PrescriptionDate",
    item_cols = c("Antibiotic", "Spectrum", "Location"),
    value_col = "NumberOfPrescriptions",
    tab_col = "Location"
  ),
  outputspec = outputspec_interactive(
    sync_axis_range = FALSE
  ),
  alertspec = alertspec(
    alert_rules = ars_restricted
  ),
  report_title = "mantis report with alerts",
  dataset_description = "Antibiotic prescriptions by site",
  save_filename = "example_prescription_numbers_interactive_alerts_restricted",
  show_progress = TRUE
)

The report now shows two rules for Coamoxiclav and one rule for Metronidazole.