The ggtime package extends the capabilities of ‘ggplot2’ by providing grammatical elements and plot helpers designed for visualizing time series patterns. These functions use calendar structures implemented in the mixtime package to help explore common time series patterns including trend, seasonality, cycles, and holidays.
The plot helper functions make use of the tsibble data format in order to quickly and easily produce common time series plots. These plots can also be constructed with the underlying grammar elements, which allows greater flexibility in producing custom time series visualisations. The examples below cover both: plot helpers first, then the grammar elements they’re built from.
You can install the stable version from CRAN:
install.packages("ggtime")You can install the development version of ggtime from GitHub with:
# install.packages("remotes")
remotes::install_github("mitchelloharawild/ggtime")Plot helper functions turn a tsibble into a complete time series graphic in one call, such as a time plot or a seasonal plot. They’re quick to use, but only offer as much customisation as their arguments allow.
The simplest time series visualisation is the time plot, which shows time continuously on the x-axis with the measured variable on the y-axis. This is useful for identifying patterns that persist over a long period of time, such as trends and seasonality. autoplot() creates a time plot directly from a tsibble.
library(ggtime)
library(ggplot2)
library(tsibble)
library(dplyr)
tsibbledata::aus_production |>
autoplot(Beer)
To see the shape of the annual seasonal pattern, it’s more useful to show time cyclically on the x-axis, making it easier to identify the peaks, troughs, and overall shape of the seasonality. gg_season() creates this seasonal plot from a tsibble.
tsibbledata::aus_production |>
gg_season(Beer)
ggtime includes several other plot helpers for exploring and diagnosing time series. gg_subseries() and gg_lag() show seasonal changes over time and relationships with past values; gg_arma() and gg_irf() plot characteristic ARMA roots and impulse response functions; and gg_tsdisplay()/gg_tsresiduals() combine several of these into a single ensemble for exploring a series or diagnosing a model’s residuals. autoplot()/autolayer() extend beyond tsibbles too, dispatching on the model output from the fable/feasts ecosystem to plot forecasts and their prediction intervals (fbl_ts), the components of a decomposition (dcmp_ts), and auto-/cross-correlation results (tbl_cf).
For full control over a time series plot’s appearance, ggtime’s grammar extensions add time-aware geoms, scales, and coordinate systems that behave like any other ggplot2 component. Use them to combine layers, apply your own themes and colour scales, and build visualisations the plot helpers don’t cover.
geom_time_line() is a time-aware extension of ggplot2::geom_line() that keeps a line’s slope an accurate reflection of the rate of change, even across timezone changes, gaps, and duplicated time points.
tsibbledata::aus_production |>
ggplot(aes(x = Quarter, y = Beer)) +
geom_time_line(colour = "steelblue")
scale_x_mixtime() is the position scale behind every mixtime time axis, applied automatically whenever a mixtime vector is mapped to a plot. It maps time points of different granularities onto one shared axis, as shown below with quarterly and annual Beer production drawn together, and takes calendrical durations for breaks (time_breaks) and calendar-aware format strings for labels (time_labels).
aus_beer <- tsibbledata::aus_production |>
as_tibble() |>
transmute(Quarter = mixtime::yearquarter(as.Date(Quarter)), Beer)
aus_beer_annual <- aus_beer |>
group_by(Quarter = mixtime::year(Quarter)) |>
summarise(Beer = mean(Beer), .groups = "drop")
bind_rows(
quarterly = aus_beer,
annual = aus_beer_annual,
.id = "granularity"
) |>
ggplot(aes(Quarter, Beer, colour = granularity)) +
geom_time_line() +
scale_x_mixtime(time_breaks = mixtime::years(10L))
coord_loop() loops the time axis around a calendrical period, so a continuous time axis can be compared cyclically instead of being discretised into a seasonal factor. Looping the time plot yearly reveals the same seasonal shape as the seasonal plot above, built entirely from grammar.
aus_beer |>
ggplot(aes(x = Quarter, y = Beer)) +
geom_time_line(colour = "steelblue") +
coord_loop(time_loops = mixtime::years(1L))
coord_calendar() arranges time into a calendar-like grid of rows and columns, useful for visualising events over short intervals within a long time span, such as holidays. Arranging hourly pedestrian counts into a weekly calendar reveals a surge in activity at one sensor during the Australian Open in late January.
tsibble::pedestrian |>
mutate(Time = mixtime::datetime(Date_Time)) |>
filter(Time < mixtime::datetime("2015-02-01 00:00:00")) |>
ggplot(aes(x = Time, y = Count, colour = Sensor)) +
geom_line() +
coord_calendar(rows = mixtime::weeks(1L), cols = NULL) +
theme(legend.position = "bottom")