R Dygraphs: How to Visualize Time Series Data in R and R Shiny

Reading time:
time
min
By:
Dario Radečić
June 25, 2024

When it comes to finding an R package capable of making interactive visualizations out of the box while also working flawlessly with R Shiny, you don’t have that many options. Sure, there’s Highcarts, but what if you’re looking for something more specialized for time series?

Well, that’s where R Dygraphs chime in! This package serves as an R interface to a popular JavaScript library, and it works like a charm in R scripts and R Shiny. We’ll explore both options today.

After reading, you’ll know how to:

  • Plot R time series objects with R Dygraphs
  • Style R Dygraphs charts, add title and axis labels, show multiple series, and customize aesthetics
  • Tweak the chart interactivity
  • Use R Dygraphs in R Shiny
What are race charts and how do you make one in R? Read our guide on visualizing stock data over time with gganimate.

Table of contents:

R Dygraphs - How to Get Started

The Dygraphs package is available on CRAN, which means you can get it by running your typical `install.packages()` command. Make sure to run this first before proceeding with the article:

install.packages("dygraphs")

And now to start using it, you’ll only need one line of code. Well, after the package import, of course. The following code snippet will create an interactive time series chart of the famous Airline passengers dataset:

library(dygraphs)

dygraph(datasets::AirPassengers)
Image 1 - First R dygraph chart

Can you believe it only took one line of code? R Dygraphs does so much for you behind the scenes. As it turns out, tweaking the chart also requires much less code than the alternative charting packages. Let’s dive into that next.

Deep Dive Into R Dygraphs - Visualize Stock Data

In this section, you’ll learn the essentials behind R Dygraphs. We’ll cover extensive chart creation and styling, multi-series plots, and interactivity - all on stock data pulled straight from the web.

How to Get Stock Data in R

The first order of business is data gathering. Since we’re working with stock data, the `quantmod` package is your friend (install if necessary). It allows you to pull stock data from Yahoo Finance for a given ticker and time frame.

The returned stock dataframe will contain the time period (daily level) as an index column, and several other attributes showing the trade volume, open, close, and adjusted price for the day. We only care about the volume and the adjusted price:

library(quantmod)

get_stock_data <- function(ticker, start_date, end_date) {
  data <- getSymbols(ticker, src = "yahoo", from = start_date, to = end_date, auto.assign = FALSE)
  # Removes the ticker name from column names
  colnames(data) <- gsub(paste0(ticker, "\\."), "", colnames(data))
  data <- data[, c("Volume", "Adjusted")]
  return(data)
}

aapl <- get_stock_data(ticker = "AAPL", start_date = "2023-01-01", end_date = "2024-01-01")
tail(aapl, 10)

The above code snippet declares a function for fetching stock data and prints the last 10 values for the AAPL ticker (Apple):

Image 2 - Last 10 days of AAPL stock data

Now in R Dygraphs, you only need to call the `dygraph()` function on the column you want to visualize - Adjusted price in our case:

dygraph(aapl$Adjusted)
Image 3 - Apple stock visualized

Hovering over the points on the line will show you the corresponding X and Y axis values:

Image 4 - R Dygraphs interactivity

is few and far between. It’s great to see Dygraphs doesn’t belong to this group, and does everything with so few lines of code.

Dygraph Customization and Chart Options

Let’s take a look at some basic tweaking options first. The `dygraph()` function can take a couple of optional parameters. For example, `main`, `xlab`, and `ylab` control the labels for the title, X-axis, and Y-axis.

The `width` and `height` parameters will set the chart to have a fixed size, rather than its content resizing with the window:

dygraph(
  aapl$Adjusted,
  main = "Apple Stock Price (AAPL)",
  xlab = "Time period",
  ylab = "Adjusted price (USD)",
  width = 1200,
  height = 800
)
Image 5 - Adding title and axis labels

We’ll keep only `main`, `xlab`, and `ylab` moving forward.

The cool thing about R Dygraphs is that it allows you to use the pipe operator (`%>%`) to chain function calls. For example, you can add an additional `dySeries()` function to control how the value axis looks and behaves.

We’ll change the line color and add square points to each data point:

dygraph(aapl$Adjusted, main = "Apple Stock Price (AAPL)", xlab = "Time period", ylab = "Adjusted price (USD)") %>%
  dySeries(color = "#0198f9", drawPoints = TRUE, pointSize = 3, pointShape = "square")
Image 6 - Styling line charts

Now we’re getting somewhere!

Dygraphs also make it possible to plot multiple series on a single chart. To demonstrate, we’ll plot the scaled version of the `Volume` attribute as a filled and stepped area chart. The scaling down process is more or less mandatory since their values are on different orders of magnitude.

While here, let’s also change the labels shown on the series legend:

aapl$VolumeScaled <- aapl[, "Volume"] / 1000000

dygraph(aapl[, c("Adjusted", "VolumeScaled")], main = "Apple Stock Price (AAPL) and Trade Volume") %>%
  dySeries("Adjusted", label = "Adjusted Price (USD)", color = "#0198f9", drawPoints = TRUE, pointSize = 3, pointShape = "square") %>%
  dySeries("VolumeScaled", label = "Trade Volume (M)", stepPlot = TRUE, fillGraph = TRUE, color = "#FF9900")
Image 7 - Multiple plots on one chart

This kind of chart might work, but scaling up/down one variable to accommodate the other leaves a lot to be desired.

Luckily, R Dygraphs has the option to display multiple axis ticks. All you need to do is to set `axis = “y2”` on the series you’re working on second:

aapl <- get_stock_data(ticker = "AAPL", start_date = "2023-01-01", end_date = "2024-01-01")

dygraph(aapl) %>%
  dySeries("Adjusted", label = "Adjusted Price (USD)", color = "#0198f9", drawPoints = TRUE, pointSize = 3, pointShape = "square") %>%
  dySeries("Volume", label = "Trade Volume (M)", stepPlot = TRUE, fillGraph = TRUE, color = "#FF9900", axis = "y2")
Image 8 - Multiple Y-axis plot ticks

You’ve now successfully plotted two variables with different orders of magnitude!

And finally, let’s take a look into interactivity. We’ll fetch stock price information for a couple of additional tickers - Microsoft and Amazon - and concatenate everything into a single XTS object:

get_stock_data <- function(ticker, start_date, end_date) {
  data <- getSymbols(ticker, src = "yahoo", from = start_date, to = end_date, auto.assign = FALSE)
  colnames(data) <- gsub(paste0(ticker, "\\."), "", colnames(data))
  data <- data[, "Adjusted"]
  return(data)
}

start_date <- "2023-01-01"
end_date <- "2024-01-01"

stock_data <- get_stock_data("AAPL", start_date, end_date)
names(stock_data) <- ("AAPL")
stock_data$MSFT <- get_stock_data("MSFT", start_date, end_date)
stock_data$AMZN <- get_stock_data("AMZN", start_date, end_date)

tail(stock_data, 10)
Image 9 - Multiple stock data

You can now use the `dyHighlight()` function to control the highlighting behavior. For example, the below code snippet will increase the width of the highlighted line, add a circle marker, and decrease the opacity of the lines not currently highlighted:

dygraph(stock_data, main = "Stock Price Comparison") %>%
  dyHighlight(
    highlightSeriesOpts = list(strokeWidth = 3),
    highlightCircleSize = 5,
    highlightSeriesBackgroundAlpha = 0.5
  )
Image 10 - Multiple line chart with highlights

You can also see how highlighting a point on one series also highlights the same point in time on others. R Dygraphs does this synchronization automatically - you don’t have to lift a finger!

And now with the basics of time series visualization under your belt, let’s take a look at implementation in R Shiny!

R Dygraphs in R Shiny - Build an App From Scratch

The idea behind the Shiny application you’re about to build is simple:

  • Give the user the option to select a stock ticker from a predefined list
  • Allow the user to change start/end dates for the stock analysis time window
  • Display historic stock prices, trade volume, and daily return percentage

To use Dygraphs in R Shiny, you’ll want to leverage the built-in `dygraphOutput()` function in the UI, and `renderDygraph()` server.

The `get_stock_data()` function will get the stock data for a given ticker and date range for you, and it will also calculate daily returns.

Moving further, the UI code is self-explanatory. It just contains the required components for input and output elements.

The server function is where things get interesting. First, we need to update date inputs on the fly through the `observe()` function, so that the user can’t select an end date that’s lower than the start date (and vice versa). Chart data is stored in `stock_data` reactive value and is referenced in chart code down below:

library(dplyr)
library(shiny)
library(dygraphs)

# Constants
allowed_tickers <- c("AAPL", "AMZN", "GOOGL", "META", "MSFT", "NVDA", "TSLA")
allowed_min_date <- as.Date("2010-01-01")
allowed_max_date <- Sys.Date() - 1

# Custom functions for getting and organizing data
get_stock_data <- function(ticker, start_date, end_date) {
  data <- getSymbols(ticker, src = "yahoo", from = start_date, to = end_date, auto.assign = FALSE)
  colnames(data) <- gsub(paste0(ticker, "\\."), "", colnames(data))
  data <- data[, c("Volume", "Adjusted")]
  data <- data.frame(Date = index(data), coredata(data))
  # In addition to what we had before, also calculate daily returns
  data <- data %>%
    arrange(Date) %>%
    mutate(DailyReturn = (Adjusted / lag(Adjusted) - 1) * 100) %>%
    na.omit()
  return(as.xts(data))
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      tags$h3("Stock price analyzer"),
      tags$hr(),
      selectInput(inputId = "inTicker", label = "Stock ticker:", choices = allowed_tickers, selected = allowed_tickers[1]),
      dateInput(inputId = "inStartDate", label = "Start date:", value = as.Date("2023-01-01"), min = allowed_min_date, max = allowed_max_date),
      dateInput(inputId = "inEndDate", label = "End date:", value = allowed_max_date, min = allowed_min_date, max = allowed_max_date)
    ),
    mainPanel(
      dygraphOutput("graphPrice"),
      dygraphOutput("graphVolume"),
      dygraphOutput("graphReturns")
    )
  )
)


server <- function(input, output, session) {
  # Make sure the dates don't get messed up
  observe({
    updateDateInput(session, "inStartDate", max = input$inEndDate - 1)
  })
  observe({
    updateDateInput(session, "inEndDate", min = input$inStartDate + 1)
  })

  # Update the data as we go
  stock_data <- reactive({
    get_stock_data(ticker = input$inTicker, start_date = input$inStartDate, end_date = input$inEndDate)
  })

  # Display charts
  output$graphPrice <- renderDygraph({
    dygraph(stock_data()$Adjusted, main = paste0(input$inTicker, " Stock Price (USD)")) %>%
      dySeries("Adjusted", label = "Adjusted price")
  })

  output$graphVolume <- renderDygraph({
    dygraph(stock_data()$Volume, main = paste0(input$inTicker, " Trade Volume")) %>%
      dySeries("Volume", label = "Trade volume", stepPlot = TRUE, fillGraph = TRUE, color = "#FF9900")
  })

  output$graphReturns <- renderDygraph({
    dygraph(stock_data()$DailyReturn, main = paste0(input$inTicker, " Daily Returns (%)")) %>%
      dySeries("DailyReturn", label = "Daily returns", color = "#cc0000") %>%
      dyLimit(0)
  })
}


shinyApp(ui = ui, server = server)

You’ll see the following Shiny application after running the code:

Image 11 - R Shiny app with R Dygraphs

Everything works like a charm! R Dygraphs integrates nicely with R Shiny, and the only thing you have to worry about is the data format going into the visualizations. It has to be an XTS object - a plain dataframe won’t suffice.

Summing up R Dygraphs

If there’s one thing R doesn’t lack, it has to be options for data visualization. Even when R-native ones aren’t enough, there are plenty of alternatives from different programming languages, such as JavaScript.

R Dygraphs is one such option specializing in time series data visualization. It works exceptionally well with XTS objects and sets the record for the least amount of code the developer has to write. All charts are interactive by default, which isn’t always a given with R, and the package has superb R Shiny support. What more do you need?

What are your thoughts on time series visualization with R Dygraphs? Do you use it daily or do you prefer an alternative package? Make sure to let us know in our Slack community.

Is R the right choice for analyzing huge datasets? Here’s how well it does in a 1 billion row challenge.

Have questions or insights?

Engage with experts, share ideas and take your data journey to the next level!

Is Your Software GxP Compliant?

Download a checklist designed for clinical managers in data departments to make sure that software meets requirements for FDA and EMA submissions.
Explore Possibilities

Share Your Data Goals with Us

From advanced analytics to platform development and pharma consulting, we craft solutions tailored to your needs.

Talk to our Experts
data visualization
shiny