From 51056143b3d6cecd1a397d73778ebf906344852b Mon Sep 17 00:00:00 2001 From: nikosbosse Date: Mon, 4 Sep 2023 10:25:12 +0200 Subject: [PATCH 1/3] Create an S3 method for plot_avail_forecasts --- NAMESPACE | 2 +- NEWS.md | 3 +- R/avail_forecasts.R | 2 + R/plot.R | 81 ++++++++++++++----- ... plot.scoringutils_available_forecasts.Rd} | 40 ++++----- man/plot_avail_forecasts.Rd | 34 ++++++++ vignettes/scoringutils.Rmd | 4 +- 7 files changed, 119 insertions(+), 47 deletions(-) rename man/{plot_available_forecasts.Rd => plot.scoringutils_available_forecasts.Rd} (54%) create mode 100644 man/plot_avail_forecasts.Rd diff --git a/NAMESPACE b/NAMESPACE index 0ba840341..c4e3a3ad2 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +S3method(plot,scoringutils_available_forecasts) S3method(print,scoringutils_check) export(abs_error) export(add_coverage) @@ -29,7 +30,6 @@ export(pairwise_comparison) export(pit) export(pit_sample) export(plot_avail_forecasts) -export(plot_available_forecasts) export(plot_correlation) export(plot_heatmap) export(plot_interval_coverage) diff --git a/NEWS.md b/NEWS.md index 727c865ba..bfa62d240 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,9 +3,10 @@ This minor update addresses comments made by review from the Journal of Statistical Software (see preprint of the manuscript [here](https://arxiv.org/abs/2205.07090)). ## Package updates -- the function `avail_forecasts()` was renamed to `available_forecasts()` for consistency with `available_metrics()`. Similarly, `plot_avail_forecasts()` was renamed to `plot_available_forecasts()`. The old functions, `avail_forecasts()` and `plot_avail_forecasts()` are still available as aliases. +- the function `avail_forecasts()` was renamed to `available_forecasts()` for consistency with `available_metrics()`. The old function, `avail_forecasts()` is still available as an alias. - For clarity, the output column in `avail_forecasts()` was renamed from "Number forecasts" to "count". - `available_forecasts()` now also displays combinations where there are 0 forecasts, instead of silently dropping corresponding rows. +- `plot_avail_forecasts()` has been deprecated in favour of an S3 method for `plot()`. An alias is still available, but will be removed in the future. # scoringutils 1.2.1 diff --git a/R/avail_forecasts.R b/R/avail_forecasts.R index 046ca9b35..cef7f8605 100644 --- a/R/avail_forecasts.R +++ b/R/avail_forecasts.R @@ -70,6 +70,8 @@ available_forecasts <- function(data, out <- merge(out, out_empty, by = by, all.y = TRUE) out[, count := nafill(count, fill = 0)] + class(out) <- c("scoringutils_available_forecasts", class(out)) + return(out[]) } diff --git a/R/plot.R b/R/plot.R index a9124f66c..165460dc8 100644 --- a/R/plot.R +++ b/R/plot.R @@ -941,14 +941,14 @@ plot_pit <- function(pit, #' #' @description #' Visualise Where Forecasts Are Available -#' -#' @param available_forecasts data.frame with a column called `count` +#' @inheritParams print.scoringutils_check +#' @param x an S3 object of class "scoringutils_available_forecasts" #' as produced by [available_forecasts()] -#' @param y character vector of length one that denotes the name of the column +#' @param yvar character vector of length one that denotes the name of the column #' to appear on the y-axis of the plot. Default is "model". -#' @param x character vector of length one that denotes the name of the column +#' @param xvar character vector of length one that denotes the name of the column #' to appear on the x-axis of the plot. Default is "forecast_date". -#' @param make_x_factor logical (default is TRUE). Whether or not to convert +#' @param make_xvar_factor logical (default is TRUE). Whether or not to convert #' the variable on the x-axis to a factor. This has an effect e.g. if dates #' are shown on the x-axis. #' @param show_numbers logical (default is `TRUE`) that indicates whether @@ -963,27 +963,35 @@ plot_pit <- function(pit, #' available_forecasts <- available_forecasts( #' example_quantile, by = c("model", "target_type", "target_end_date") #' ) -#' plot_available_forecasts( -#' available_forecasts, x = "target_end_date", show_numbers = FALSE +#' plot( +#' available_forecasts, xvar = "target_end_date", show_numbers = FALSE #' ) + #' facet_wrap("target_type") -plot_available_forecasts <- function(available_forecasts, - y = "model", - x = "forecast_date", - make_x_factor = TRUE, - show_numbers = TRUE) { - available_forecasts <- as.data.table(available_forecasts) +plot.scoringutils_available_forecasts <- function(x, + yvar = "model", + xvar = "forecast_date", + make_xvar_factor = TRUE, + show_numbers = TRUE, + ...) { + + # input checks + if (!inherits(x, "scoringutils_available_forecasts")) { + stop("The input object must be of class 'scoringutils_available_forecasts', ", + "as produced by the function available_forecasts()") + } - if (make_x_factor) { - available_forecasts[, eval(x) := as.factor(get(x))] + x <- as.data.table(x) + + if (make_xvar_factor) { + x[, eval(xvar) := as.factor(get(xvar))] } - setnames(available_forecasts, old = "count", new = "Count") + setnames(x, old = "count", new = "Count") plot <- ggplot( - available_forecasts, - aes(y = .data[[y]], x = .data[[x]]) + x, + aes(y = .data[[yvar]], x = .data[[xvar]]) ) + geom_tile(aes(fill = `Count`), width = 0.97, height = 0.97 @@ -1010,9 +1018,42 @@ plot_available_forecasts <- function(available_forecasts, } -#' @rdname plot_available_forecasts +#' @title Visualise Where Forecasts Are Available (deprecated) +#' +#' @description +#' Old version of [plot.scoringutils_available_forecasts()] for compatibility. +#' @inheritParams plot.scoringutils_available_forecasts +#' @param available_forecasts an S3 object of class "scoringutils_available_forecasts" +#' as produced by [available_forecasts()] +#' @param y character vector of length one that denotes the name of the column +#' to appear on the y-axis of the plot. Default is "model". +#' @param x character vector of length one that denotes the name of the column +#' to appear on the x-axis of the plot. Default is "forecast_date". +#' @param make_xv_factor logical (default is TRUE). Whether or not to convert +#' the variable on the x-axis to a factor. This has an effect e.g. if dates +#' are shown on the x-axis. #' @export -plot_avail_forecasts <- plot_available_forecasts +plot_avail_forecasts <- function(available_forecasts, + y = "model", + x = "forecast_date", + make_x_factor = TRUE, + show_numbers = TRUE) { + + lifecycle::deprecate_warn( + "1.2.2", "plot_avail_forecasts()", + "plot()" + ) + + plot.scoringutils_available_forecasts( + x = available_forecasts, + yvar = y, + xvar = x, + make_xvar_factor = make_x_factor, + show_numbers = show_numbers + ) +} + + #' @title Plot Correlation Between Metrics diff --git a/man/plot_available_forecasts.Rd b/man/plot.scoringutils_available_forecasts.Rd similarity index 54% rename from man/plot_available_forecasts.Rd rename to man/plot.scoringutils_available_forecasts.Rd index 58a089a07..f11e0dc5d 100644 --- a/man/plot_available_forecasts.Rd +++ b/man/plot.scoringutils_available_forecasts.Rd @@ -1,42 +1,36 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/plot.R -\name{plot_available_forecasts} -\alias{plot_available_forecasts} -\alias{plot_avail_forecasts} +\name{plot.scoringutils_available_forecasts} +\alias{plot.scoringutils_available_forecasts} \title{Visualise Where Forecasts Are Available} \usage{ -plot_available_forecasts( - available_forecasts, - y = "model", - x = "forecast_date", - make_x_factor = TRUE, - show_numbers = TRUE -) - -plot_avail_forecasts( - available_forecasts, - y = "model", - x = "forecast_date", - make_x_factor = TRUE, - show_numbers = TRUE +\method{plot}{scoringutils_available_forecasts}( + x, + yvar = "model", + xvar = "forecast_date", + make_xvar_factor = TRUE, + show_numbers = TRUE, + ... ) } \arguments{ -\item{available_forecasts}{data.frame with a column called \code{count} +\item{x}{an S3 object of class "scoringutils_available_forecasts" as produced by \code{\link[=available_forecasts]{available_forecasts()}}} -\item{y}{character vector of length one that denotes the name of the column +\item{yvar}{character vector of length one that denotes the name of the column to appear on the y-axis of the plot. Default is "model".} -\item{x}{character vector of length one that denotes the name of the column +\item{xvar}{character vector of length one that denotes the name of the column to appear on the x-axis of the plot. Default is "forecast_date".} -\item{make_x_factor}{logical (default is TRUE). Whether or not to convert +\item{make_xvar_factor}{logical (default is TRUE). Whether or not to convert the variable on the x-axis to a factor. This has an effect e.g. if dates are shown on the x-axis.} \item{show_numbers}{logical (default is \code{TRUE}) that indicates whether or not to show the actual count numbers on the plot} + +\item{...}{additional arguments (not used here)} } \value{ ggplot object with a plot of interval coverage @@ -49,8 +43,8 @@ library(ggplot2) available_forecasts <- available_forecasts( example_quantile, by = c("model", "target_type", "target_end_date") ) -plot_available_forecasts( - available_forecasts, x = "target_end_date", show_numbers = FALSE +plot( + available_forecasts, xvar = "target_end_date", show_numbers = FALSE ) + facet_wrap("target_type") } diff --git a/man/plot_avail_forecasts.Rd b/man/plot_avail_forecasts.Rd new file mode 100644 index 000000000..d2eebfdb4 --- /dev/null +++ b/man/plot_avail_forecasts.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/plot.R +\name{plot_avail_forecasts} +\alias{plot_avail_forecasts} +\title{Visualise Where Forecasts Are Available (deprecated)} +\usage{ +plot_avail_forecasts( + available_forecasts, + y = "model", + x = "forecast_date", + make_x_factor = TRUE, + show_numbers = TRUE +) +} +\arguments{ +\item{available_forecasts}{an S3 object of class "scoringutils_available_forecasts" +as produced by \code{\link[=available_forecasts]{available_forecasts()}}} + +\item{y}{character vector of length one that denotes the name of the column +to appear on the y-axis of the plot. Default is "model".} + +\item{x}{character vector of length one that denotes the name of the column +to appear on the x-axis of the plot. Default is "forecast_date".} + +\item{show_numbers}{logical (default is \code{TRUE}) that indicates whether +or not to show the actual count numbers on the plot} + +\item{make_xv_factor}{logical (default is TRUE). Whether or not to convert +the variable on the x-axis to a factor. This has an effect e.g. if dates +are shown on the x-axis.} +} +\description{ +Old version of \code{\link[=plot.scoringutils_available_forecasts]{plot.scoringutils_available_forecasts()}} for compatibility. +} diff --git a/vignettes/scoringutils.Rmd b/vignettes/scoringutils.Rmd index 1c7cd8b26..b4dd0bf16 100644 --- a/vignettes/scoringutils.Rmd +++ b/vignettes/scoringutils.Rmd @@ -87,12 +87,12 @@ available_forecasts(example_quantile, by = c("model", "target_type")) We see that 'epiforecasts-EpiNow2' has some missing forecasts for the deaths forecast target and that UMass-MechBayes has no case forecasts. -This information can also be visualised using the `plot_available_forecasts()` function: +This information can also be visualised using `plot()`: ```{r, fig.width=11, fig.height=6} example_quantile %>% available_forecasts(by = c("model", "forecast_date", "target_type")) %>% - plot_available_forecasts() + + plot() + facet_wrap(~ target_type) ``` From c4baa73520a4d6a1bccf4fd8bf3edada6352ca58 Mon Sep 17 00:00:00 2001 From: nikosbosse Date: Mon, 4 Sep 2023 10:37:27 +0200 Subject: [PATCH 2/3] fix test and minor typos --- R/plot.R | 2 +- man/plot_avail_forecasts.Rd | 8 ++++---- tests/testthat/test-plot_avail_forecasts.R | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/R/plot.R b/R/plot.R index 165460dc8..9e0b61ee2 100644 --- a/R/plot.R +++ b/R/plot.R @@ -1029,7 +1029,7 @@ plot.scoringutils_available_forecasts <- function(x, #' to appear on the y-axis of the plot. Default is "model". #' @param x character vector of length one that denotes the name of the column #' to appear on the x-axis of the plot. Default is "forecast_date". -#' @param make_xv_factor logical (default is TRUE). Whether or not to convert +#' @param make_x_factor logical (default is TRUE). Whether or not to convert #' the variable on the x-axis to a factor. This has an effect e.g. if dates #' are shown on the x-axis. #' @export diff --git a/man/plot_avail_forecasts.Rd b/man/plot_avail_forecasts.Rd index d2eebfdb4..ce9580d1e 100644 --- a/man/plot_avail_forecasts.Rd +++ b/man/plot_avail_forecasts.Rd @@ -22,12 +22,12 @@ to appear on the y-axis of the plot. Default is "model".} \item{x}{character vector of length one that denotes the name of the column to appear on the x-axis of the plot. Default is "forecast_date".} -\item{show_numbers}{logical (default is \code{TRUE}) that indicates whether -or not to show the actual count numbers on the plot} - -\item{make_xv_factor}{logical (default is TRUE). Whether or not to convert +\item{make_x_factor}{logical (default is TRUE). Whether or not to convert the variable on the x-axis to a factor. This has an effect e.g. if dates are shown on the x-axis.} + +\item{show_numbers}{logical (default is \code{TRUE}) that indicates whether +or not to show the actual count numbers on the plot} } \description{ Old version of \code{\link[=plot.scoringutils_available_forecasts]{plot.scoringutils_available_forecasts()}} for compatibility. diff --git a/tests/testthat/test-plot_avail_forecasts.R b/tests/testthat/test-plot_avail_forecasts.R index f326bd554..9f2efea6b 100644 --- a/tests/testthat/test-plot_avail_forecasts.R +++ b/tests/testthat/test-plot_avail_forecasts.R @@ -4,8 +4,8 @@ test_that("plot_available_forecasts() works as expected", { by = c("model", "target_type", "target_end_date") ) ) - p <- plot_available_forecasts(available_forecasts, - x = "target_end_date", show_numbers = FALSE + p <- plot(available_forecasts, + xvar = "target_end_date", show_numbers = FALSE ) + facet_wrap("target_type") expect_s3_class(p, "ggplot") From 6529c40c5bcfa7b84964bff842479967d38d3eec Mon Sep 17 00:00:00 2001 From: nikosbosse Date: Tue, 5 Sep 2023 09:06:17 +0200 Subject: [PATCH 3/3] remove unnecessary input check --- R/plot.R | 7 ------- 1 file changed, 7 deletions(-) diff --git a/R/plot.R b/R/plot.R index 9e0b61ee2..52813d0f8 100644 --- a/R/plot.R +++ b/R/plot.R @@ -974,13 +974,6 @@ plot.scoringutils_available_forecasts <- function(x, make_xvar_factor = TRUE, show_numbers = TRUE, ...) { - - # input checks - if (!inherits(x, "scoringutils_available_forecasts")) { - stop("The input object must be of class 'scoringutils_available_forecasts', ", - "as produced by the function available_forecasts()") - } - x <- as.data.table(x) if (make_xvar_factor) {