--- title: "Time series" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Time series} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set(collapse = FALSE, comment = "", fig.width = 7, fig.height = 4, dpi = 96, dev.args = list(bg = "transparent")) # Console colour carries no meaning on a rendered page. pkgdown turns it on for # its own build, and the escape sequences then reach the reader as literal text, # so colour is switched off here for a plain vignette render and a site build # alike. The fixed width keeps printed output inside the documentation column. options(cli.num_colors = 1, cli.hyperlink = FALSE, crayon.enabled = FALSE, width = 80) # Figures on the package website sit on a warm off-white page in light mode and # are inverted by pkgdown in dark mode, so an opaque background would read as a # pale slab one way and a black plate the other. Two things paint one. The # device # canvas is made transparent by `dev.args` above, and theme_depictr() then # inherits theme_minimal()'s white plot.background, which is drawn over that # canvas, so it is cleared as each figure is printed. This is deliberately a # vignette-level choice: theme_depictr() keeps its opaque background, which is # what a figure saved for a paper wants. transparent_bg <- ggplot2::theme( plot.background = ggplot2::element_rect(fill = NA, colour = NA), panel.background = ggplot2::element_rect(fill = NA, colour = NA) ) knit_print.ggplot <- function(x, ...) knitr::normal_print(x + transparent_bg) knit_print.patchwork <- function(x, ...) knitr::normal_print(x & transparent_bg) library(depictr) ``` depictr provides a small, consistent set of time-series plots. The examples use the bundled `monthly_sales` dataset: two product lines (`indoor` and `outdoor`), each with six years of monthly observations carrying a trend, a twelve-month seasonal cycle and noise. ## Plotting one or several series `timeseries_plot()` accepts a `ts` object, a numeric vector or a data frame with time, value and (optionally) group columns. Passing the long-form data frame with a grouping column draws both series at once, each in its own colour, and a moving-average overlay is one argument away. ```{r} timeseries_plot(monthly_sales, time = date, value = sales, group = series, rolling = 12, title = "Monthly sales by product line", y_lab = "Units") ``` For the single-series views (decomposition, autocorrelation, the seasonal plot and forecasting) we extract one line as a monthly `ts` object of frequency 12. ```{r} indoor <- subset(monthly_sales, series == "indoor") indoor <- indoor[order(indoor$date), ] indoor_ts <- ts(indoor$sales, start = c(2018, 1), frequency = 12) ``` ## Decomposition `decompose_plot()` separates a seasonal series into trend, seasonal and remainder components. Use `method = "stl"` (the default, loess-based) or `method = "classical"`. Setting `confidence = TRUE` shades a band around the smoothed trend, from the spread of the remainder, so the scale of the unexplained variation is visible rather than implied by the line alone. ```{r, fig.height = 6} decompose_plot(indoor_ts, confidence = TRUE, title = "Indoor sales, decomposed") ``` Classical decomposition instead holds the seasonal component fixed across the whole series, where STL lets it evolve from year to year. ```{r, fig.height = 6} decompose_plot(indoor_ts, method = "classical", title = "Indoor sales, classical decomposition") ``` ## Autocorrelation `acf_plot()` draws the autocorrelation (or, with `type = "partial"`, the partial autocorrelation) function, with approximate significance bounds. The spikes at multiples of twelve are the annual seasonality. ```{r, fig.height = 3.4} acf_plot(indoor_ts) ``` ```{r, fig.height = 3.4} acf_plot(indoor_ts, type = "partial") ``` ## The seasonal pattern up close `seasonal_plot()` draws a seasonal-subseries (cycle) plot: one small panel per month, with the value traced across successive years and a reference line at each month's mean. This shows the seasonal shape (differences *between* panels) and the year-on-year trend within each month (the slope *inside* each panel) at the same time, something a single overlaid line cannot do. ```{r, fig.height = 3.8} seasonal_plot(indoor_ts, title = "Indoor sales: monthly subseries") ``` With `style = "season"` every year becomes its own line over the months on a shared axis, which is handy for spotting an unusual year. ```{r, fig.height = 4} seasonal_plot(indoor_ts, style = "season", title = "Indoor sales: one line per year") ``` ## Forecasting `ts_forecast()` is a lightweight, dependency-free forecaster: it decomposes the series with STL, extrapolates the recent trend, carries the seasonal pattern forward and returns point forecasts with prediction intervals that widen with the horizon. ```{r} fc <- ts_forecast(indoor_ts, h = 18, level = 0.9) head(fc) ``` Passing an integer horizon straight to `timeseries_plot()` overlays that forecast on the history: the point forecast continues the line and the shaded ribbon shows the (growing) 90% prediction interval. ```{r, fig.height = 4} timeseries_plot(indoor_ts, forecast = 18, level = 0.9, title = "Indoor sales with an 18-month forecast", y_lab = "Units") ``` For a fully specified statistical model, fit it yourself (for example with `forecast::forecast()`) and pass the resulting `time`/`fit`/`lwr`/`upr` columns to `timeseries_plot(forecast = )` as a data frame.