Skip to contents

A workhorse time-series plotting function that generates interactive plotly plots, consolidates 20+ lines of ggplot2 code, and scales well to many time series.


  .color_var = NULL,
  .facet_vars = NULL,
  .facet_ncol = 1,
  .facet_nrow = 1,
  .facet_scales = "free_y",
  .facet_dir = "h",
  .facet_collapse = FALSE,
  .facet_collapse_sep = " ",
  .facet_strip_remove = FALSE,
  .line_color = "#2c3e50",
  .line_size = 0.5,
  .line_type = 1,
  .line_alpha = 1,
  .y_intercept = NULL,
  .y_intercept_color = "#2c3e50",
  .x_intercept = NULL,
  .x_intercept_color = "#2c3e50",
  .smooth = TRUE,
  .smooth_period = "auto",
  .smooth_message = FALSE,
  .smooth_span = NULL,
  .smooth_degree = 2,
  .smooth_color = "#3366FF",
  .smooth_size = 1,
  .smooth_alpha = 1,
  .legend_show = TRUE,
  .title = "Time Series Plot",
  .x_lab = "",
  .y_lab = "",
  .color_lab = "Legend",
  .interactive = TRUE,
  .plotly_slider = FALSE,
  .trelliscope = FALSE,
  .trelliscope_params = list()



A tibble or data.frame with a time-based column


A column containing either date or date-time values


A column containing numeric values


A categorical column that can be used to change the line color


One or more grouping columns that broken out into ggplot2 facets. These can be selected using tidyselect() helpers (e.g contains()).


Number of facet columns.


Number of facet rows (only used for .trelliscope = TRUE)


Control facet x & y-axis ranges. Options include "fixed", "free", "free_y", "free_x"


The direction of faceting ("h" for horizontal, "v" for vertical). Default is "h".


Multiple facets included on one facet strip instead of multiple facet strips.


The separator used for collapsing facets.


Whether or not to remove the strip and text label for each facet.


Line color. Overrided if .color_var is specified.


Line size.


Line type.


Line alpha (opacity). Range: (0, 1).


Value for a y-intercept on the plot


Color for the y-intercept


Value for a x-intercept on the plot


Color for the x-intercept


Logical - Whether or not to include a trendline smoother. Uses See smooth_vec() to apply a LOESS smoother.


Number of observations to include in the Loess Smoother. Set to "auto" by default, which uses tk_get_trend() to determine a logical trend cycle.


Logical. Whether or not to return the trend selected as a message. Useful for those that want to see what .smooth_period was selected.


Percentage of observations to include in the Loess Smoother. You can use either period or span. See smooth_vec().


Flexibility of Loess Polynomial. Either 0, 1, 2 (0 = lest flexible, 2 = more flexible).


Smoother line color


Smoother line size


Smoother alpha (opacity). Range: (0, 1).


Toggles on/off the Legend


Title for the plot


X-axis label for the plot


Y-axis label for the plot


Legend label if a color_var is used.


Returns either a static (ggplot2) visualization or an interactive (plotly) visualization


If TRUE, returns a plotly date range slider.


Returns either a normal plot or a trelliscopejs plot (great for many time series) Must have trelliscopejs installed.


Pass parameters to the trelliscopejs::facet_trelliscope() function as a list(). The only parameters that cannot be passed are:

  • ncol: use .facet_ncol

  • nrow: use .facet_nrow

  • scales: use facet_scales

  • as_plotly: use .interactive


A static ggplot2 plot or an interactive plotly plot


plot_time_series() is a scalable function that works with both ungrouped and grouped data.frame objects (and tibbles!).

Interactive by Default

plot_time_series() is built for exploration using:

  • Interactive Plots: plotly (default) - Great for exploring!

  • Static Plots: ggplot2 (set .interactive = FALSE) - Great for PDF Reports

By default, an interactive plotly visualization is returned.

Scalable with Facets & Dplyr Groups

plot_time_series() returns multiple time series plots using ggplot2 facets:

  • group_by() - If groups are detected, multiple facets are returned

  • plot_time_series(.facet_vars) - You can manually supply facets as well.

Can Transform Values just like ggplot

The .values argument accepts transformations just like ggplot2. For example, if you want to take the log of sales you can use a call like plot_time_series(date, log(sales)) and the log transformation will be applied.

Smoother Period / Span Calculation

The .smooth = TRUE option returns a smoother that is calculated based on either:

  1. A .smooth_period: Number of observations

  2. A .smooth_span: A percentage of observations

By default, the .smooth_period is automatically calculated using 75% of the observertions. This is the same as geom_smooth(method = "loess", span = 0.75).

A user can specify a time-based window (e.g. .smooth_period = "1 year") or a numeric value (e.g. smooth_period = 365).

Time-based windows return the median number of observations in a window using tk_get_trend().



# Works with individual time series
FANG %>%
    filter(symbol == "FB") %>%
    plot_time_series(date, adjusted, .interactive = FALSE)

# Works with groups
FANG %>%
    group_by(symbol) %>%
    plot_time_series(date, adjusted,
                     .facet_ncol  = 2,     # 2-column layout
                     .interactive = FALSE)

# Can also group inside & use .color_var
FANG %>%
    mutate(year = year(date)) %>%
    plot_time_series(date, adjusted,
                     .facet_vars     = c(symbol, year), # add groups/facets
                     .color_var      = year,            # color by year
                     .facet_ncol     = 4,
                     .facet_scales   = "free",
                     .facet_collapse = TRUE,  # combine group strip text into 1 line
                     .interactive    = FALSE)

# Can apply transformations to .value or .color_var
# - .value = log(adjusted)
# - .color_var = year(date)
FANG %>%
    plot_time_series(date, log(adjusted),
                     .color_var    = year(date),
                     .facet_vars   = contains("symbol"),
                     .facet_ncol   = 2,
                     .facet_scales = "free",
                     .y_lab        = "Log Scale",
                     .interactive  = FALSE)