Time Series and Date Axes in R

How to plot date and time in R.


New to Plotly?

Plotly is a free and open-source graphing library for R. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.

Time Series using Axes of type date

Time series can be represented using plotly functions (line, scatter, bar etc). For more examples of such charts, see the documentation of line and scatter plots or bar charts.

For financial applications, Plotly can also be used to create Candlestick charts and OHLC charts, which default to date axes.

Plotly doesn't auto set the data type of axis to date. We have to give the values using as.Data() for an axis to mention it's data type as date.

library(tidyquant)
library(plotly)

getSymbols("GOOG",
             from = "2018-01-01",
             to = "2019-12-31")
Click to copy
## [1] "GOOG"
Click to copy
stock <- data.frame(GOOG$GOOG.Adjusted)
stock$GOOG.Adjusted <- stock$GOOG.Adjusted/stock$GOOG.Adjusted[1]
stock <- data.frame(stock,rownames(stock))
colnames(stock) <- append('GOOG','date')

fig <- plot_ly(stock, type = 'scatter', mode = 'lines')%>%
  add_trace(x = ~date, y = ~GOOG, name = 'GOOG')%>%
  layout(showlegend = F)
options(warn = -1)

fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)


fig
Click to copy
Apr 2018Jul 2018Oct 2018Jan 2019Apr 2019Jul 2019Oct 20190.90.9511.051.11.151.21.25
dateGOOG
library(plotly)

stock <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

fig <- plot_ly(stock, type = 'scatter', mode = 'lines')%>%
  add_trace(x = ~Date, y = ~AAPL.High)%>%
  layout(showlegend = F)
fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)


fig
Click to copy
Apr 2015Jul 2015Oct 2015Jan 2016Apr 2016Jul 2016Oct 2016Jan 20179095100105110115120125130135
DateAAPL.High

Different Chart Types on Date Axes

Any kind of cartesian chart can be placed on date axes, for example this filled area chart of relative stock ticker values.

library(tidyquant)
library(plotly)

getSymbols("GOOG",
           from = "2018-01-01",
           to = "2020-01-01")
Click to copy
## [1] "GOOG"
Click to copy
stock <- data.frame(GOOG$GOOG.Adjusted)
stock$GOOG.Adjusted <- stock$GOOG.Adjusted/stock$GOOG.Adjusted[1]
stock <- data.frame(stock,rownames(stock))
colnames(stock) <- append('GOOG','date')
stock$date <- as.Date(stock$date)

fig <- plot_ly()%>%
  add_trace(data = stock, type = 'scatter', mode = 'lines', fill = 'tozeroy', x = ~date, y = ~GOOG, name = 'GOOG')%>%
  layout(showlegend = F, yaxis = list(range = c(0.8,1.25),
                                      zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6')
options(warn = -1)
fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)


fig
Click to copy
Apr 2018Jul 2018Oct 2018Jan 2019Apr 2019Jul 2019Oct 20190.80.850.90.9511.051.11.151.21.25
dateGOOG

Or this facetted area plot:

library(tidyquant)
library(plotly)
tickers = c("GOOG", "AAPL", "AMZN", "META", "NFLX", "MSFT")
for (i in tickers){
  getSymbols(i,
             from = "2018-01-01",
             to = "2019-12-31")}

x <- list(
  title = "date"
)
y <- list(
  title = "value"
)

stock <- data.frame(GOOG$GOOG.Adjusted,
                    AAPL$AAPL.Adjusted,
                    AMZN$AMZN.Adjusted,
                    META$META.Adjusted,
                    NFLX$NFLX.Adjusted,
                    MSFT$MSFT.Adjusted)
stock$GOOG.Adjusted <- stock$GOOG.Adjusted/stock$GOOG.Adjusted[1]
stock$AAPL.Adjusted <- stock$AAPL.Adjusted/stock$AAPL.Adjusted[1]
stock$AMZN.Adjusted <- stock$AMZN.Adjusted/stock$AMZN.Adjusted[1]
stock$META.Adjusted <- stock$META.Adjusted/stock$META.Adjusted[1]
stock$NFLX.Adjusted <- stock$NFLX.Adjusted/stock$NFLX.Adjusted[1]
stock$MSFT.Adjusted <- stock$MSFT.Adjusted/stock$MSFT.Adjusted[1]
stock <- data.frame(stock,rownames(stock))
colnames(stock) <- append(tickers,'Dates')

ax <- list(
  title = "",
  zeroline = FALSE,
  showline = FALSE,
  showticklabels = FALSE
)

fig1 <- plot_ly(stock, type = 'scatter', mode = 'lines', fill = 'tonexty')%>%
  add_trace(x = ~Dates, y = ~GOOG, name = 'GOOG')%>%
  layout(legend=list(title=list(text='company')), xaxis = ax, yaxis = list(range = c(0.5,2), title = 'value'))


fig2 <- plot_ly(stock, type = 'scatter', mode = 'lines', fill = 'tonexty')%>%
  add_trace(x = ~Dates, y = ~AAPL, name = 'AAPL')%>%
  layout(legend=list(title=list(text='company')), xaxis = ax, yaxis = list(range = c(0.5,2),title = '', showticklabels = FALSE))


fig3 <- plot_ly(stock, type = 'scatter', mode = 'lines', fill = 'tonexty')%>%
  add_trace(x = ~Dates, y = ~AMZN, name = 'AMZN')%>%
  layout(legend=list(title=list(text='company')), xaxis = ax, yaxis = list(range = c(0.5,2), title = 'value'))


fig4 <- plot_ly(stock, type = 'scatter', mode = 'lines', fill = 'tonexty')%>%
  add_trace(x = ~Dates, y = ~META, name = 'META')%>%
  layout(legend=list(title=list(text='company')), xaxis = ax, yaxis = list(range = c(0.5,2),title = '', showticklabels = FALSE))


fig5 <- plot_ly(stock, type = 'scatter', mode = 'lines', fill = 'tonexty')%>%
  add_trace(x = ~Dates, y = ~NFLX, name = 'NFLX')%>%
  layout(legend=list(title=list(text='company')), xaxis = list(title = 'Date'), yaxis = list(range = c(0.5,2), title = 'value'))


fig6 <- plot_ly(stock, type = 'scatter', mode = 'lines', fill = 'tonexty')%>%
  add_trace(x = ~Dates, y = ~MSFT, name = 'MSFT')%>%
  layout( legend=list(title=list(text='company')), yaxis = list(range = c(0.5,2) ,showticklabels = FALSE, title =''),  xaxis = list(title = 'Date'))


fig <- subplot(fig1, fig2, fig3, fig4, fig5, fig6,
               nrows = 3, titleY = TRUE, titleX = TRUE) %>% layout(
                 xaxis = list(zerolinecolor = '#ffff',
                              zerolinewidth = 2,
                              gridcolor = 'ffff'),
                 yaxis = list(zerolinecolor = '#ffff',
                              zerolinewidth = 2,
                              gridcolor = 'ffff'),
                 plot_bgcolor='#e5ecf6')
annotations = list(
  list(
    x = 0.225,
    y = 1.0,
    font = list(size = 10),
    text = "company=GOOG",
    xref = "paper",
    yref = "paper",
    xanchor = "center",
    yanchor = "bottom",
    showarrow = FALSE
  ),
  list(
    x = 0.775,
    y = 1,
    font = list(size = 10),
    text = "company=AAPL",
    xref = "paper",
    yref = "paper",
    xanchor = "center",
    yanchor = "bottom",
    showarrow = FALSE
  ),
  list(
    x = 0.225,
    y = 0.64,
    font = list(size = 10),
    text = "company=AMZN",
    xref = "paper",
    yref = "paper",
    xanchor = "center",
    yanchor = "bottom",
    showarrow = FALSE
  ),
  list(
    x = 0.775,
    y = 0.64,
    font = list(size = 10),
    text = "company=META",
    xref = "paper",
    yref = "paper",
    xanchor = "center",
    yanchor = "bottom",
    showarrow = FALSE
  ),
  list(
    x = 0.225,
    y = 0.315,
    font = list(size = 10),
    text = "company=NFLX",
    xref = "paper",
    yref = "paper",
    xanchor = "center",
    yanchor = "bottom",
    showarrow = FALSE
  ),
  list(
    x = 0.775,
    y = 0.315,
    font = list(size = 10),
    text = "company=MSFT",
    xref = "paper",
    yref = "paper",
    xanchor = "center",
    yanchor = "bottom",
    showarrow = FALSE
  )
)

fig <- fig %>%layout(annotations = annotations, width = 900)
options(warn = -1)
fig
Click to copy
0.511.520.511.52Jul 2018Jan 2019Jul 20190.511.52Jul 2018Jan 2019Jul 2019
companyMSFTNFLXMETAAMZNAAPLGOOGDateDatevaluevaluevaluecompany=GOOGcompany=AAPLcompany=AMZNcompany=METAcompany=NFLXcompany=MSFT

Configuring Tick Labels

By default, the tick labels (and optional ticks) are associated with a specific grid-line, and represent an instant in time, for example, "00:00 on February 1, 2018". Tick labels can be formatted using the tickformat attribute (which accepts the d3 time-format formatting strings) to display only the month and year, but they still represent an instant by default, so in the figure below, the text of the label "Feb 2018" spans part of the month of January and part of the month of February. The dtick attribute controls the spacing between gridlines, and the "M1" setting means "1 month". This attribute also accepts a number of milliseconds, which can be scaled up to days by multiplying by 24*60*60*1000.

Note that by default, the formatting of values of X and Y values in the hover label matches that of the tick labels of the corresponding axes, so when customizing the tick labels to something broad like "month", it's usually necessary to customize the hover label to something narrower like the actual date, as below.

library(tidyquant)
library(plotly)
tickers = c("GOOG", "AAPL", "AMZN", "META", "NFLX", "MSFT")
for (i in tickers){
  getSymbols(i,
             from = "2018-01-01",
             to = "2019-12-31")}
stock <- data.frame(GOOG$GOOG.Adjusted,
                    AAPL$AAPL.Adjusted,
                    AMZN$AMZN.Adjusted,
                    META$META.Adjusted,
                    NFLX$NFLX.Adjusted,
                    MSFT$MSFT.Adjusted)
stock$GOOG.Adjusted <- stock$GOOG.Adjusted/stock$GOOG.Adjusted[1]
stock$AAPL.Adjusted <- stock$AAPL.Adjusted/stock$AAPL.Adjusted[1]
stock$AMZN.Adjusted <- stock$AMZN.Adjusted/stock$AMZN.Adjusted[1]
stock$META.Adjusted <- stock$META.Adjusted/stock$META.Adjusted[1]
stock$NFLX.Adjusted <- stock$NFLX.Adjusted/stock$NFLX.Adjusted[1]
stock$MSFT.Adjusted <- stock$MSFT.Adjusted/stock$MSFT.Adjusted[1]
stock <- data.frame(stock,rownames(stock))
colnames(stock) <- append(tickers,'Dates')

fig <- plot_ly(stock, type = 'scatter', mode = 'lines')%>%
  add_trace(x = ~Dates, y = ~GOOG, name = 'GOOG')%>%
  add_trace(x = ~Dates, y = ~AAPL, name = 'AAPL')%>%
  add_trace(x = ~Dates, y = ~AMZN, name = 'AMZN')%>%
  add_trace(x = ~Dates, y = ~META, name = 'META')%>%
  add_trace(x = ~Dates, y = ~NFLX, name = 'NFLX')%>%
  add_trace(x = ~Dates, y = ~MSFT, name = 'MSFT')%>%
  layout(title = 'custom tick labels',legend=list(title=list(text='variable')),
         xaxis = list(dtick = "M1", tickformat="%b<br>%Y"), width = 1000)
options(warn = -1)
fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6')


fig
Click to copy
Feb2018Mar2018Apr2018May2018Jun2018Jul2018Aug2018Sep2018Oct2018Nov2018Dec2018Jan2019Feb2019Mar2019Apr2019May2019Jun2019Jul2019Aug2019Sep2019Oct2019Nov2019Dec20190.811.21.41.61.82
variableGOOGAAPLAMZNMETANFLXMSFTcustom tick labelsDatesGOOG

Moving Tick Labels to the Middle of the Period

new in 4.10

By setting the ticklabelmode attribute to "period" (the default is "instant") we can move the tick labels to the middle of the period they represent. The gridlines remain at the beginning of each month (thanks to dtick="M1") but the labels now span the month they refer to.

library(tidyquant)
library(plotly)
tickers = c("GOOG", "AAPL", "AMZN", "META", "NFLX", "MSFT")
for (i in tickers){
  getSymbols(i,
             from = "2018-01-01",
             to = "2019-12-31")}
stock <- data.frame(GOOG$GOOG.Adjusted,
                    AAPL$AAPL.Adjusted,
                    AMZN$AMZN.Adjusted,
                    META$META.Adjusted,
                    NFLX$NFLX.Adjusted,
                    MSFT$MSFT.Adjusted)
stock$GOOG.Adjusted <- stock$GOOG.Adjusted/stock$GOOG.Adjusted[1]
stock$AAPL.Adjusted <- stock$AAPL.Adjusted/stock$AAPL.Adjusted[1]
stock$AMZN.Adjusted <- stock$AMZN.Adjusted/stock$AMZN.Adjusted[1]
stock$META.Adjusted <- stock$META.Adjusted/stock$META.Adjusted[1]
stock$NFLX.Adjusted <- stock$NFLX.Adjusted/stock$NFLX.Adjusted[1]
stock$MSFT.Adjusted <- stock$MSFT.Adjusted/stock$MSFT.Adjusted[1]
stock <- data.frame(stock,rownames(stock))
colnames(stock) <- append(tickers,'Dates')

fig <- plot_ly(stock, type = 'scatter', mode = 'lines')%>%
  add_trace(x = ~Dates, y = ~GOOG, name = 'GOOG')%>%
  add_trace(x = ~Dates, y = ~AAPL, name = 'AAPL')%>%
  add_trace(x = ~Dates, y = ~AMZN, name = 'AMZN')%>%
  add_trace(x = ~Dates, y = ~META, name = 'META')%>%
  add_trace(x = ~Dates, y = ~NFLX, name = 'NFLX')%>%
  add_trace(x = ~Dates, y = ~MSFT, name = 'MSFT')%>%
  layout(title = 'custom tick labels with ticklabelmode="period"',legend=list(title=list(text='variable')),
         xaxis = list(dtick = "M1", tickformat="%b\n%Y",
                      ticklabelmode="period"), width = 1000)
options(warn = -1)
fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6')


fig
Click to copy
Jan2018Feb2018Mar2018Apr2018May2018Jun2018Jul2018Aug2018Sep2018Oct2018Nov2018Dec2018Jan2019Feb2019Mar2019Apr2019May2019Jun2019Jul2019Aug2019Sep2019Oct2019Nov2019Dec20190.811.21.41.61.82
variableGOOGAAPLAMZNMETANFLXMSFTcustom tick labels with ticklabelmode="period"DatesGOOG

Summarizing Time-series Data with Histograms

Plotly histograms are powerful data-aggregation tools which even work on date axes. In the figure below, we pass in daily data and display it as monthly averages by setting histfunc="avg and xbins_size="M1".

library(plotly)

stock <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
stock$Date = as.Date(stock$Date)

fig <- plot_ly(stock, x = ~AAPL.Close,y = ~Date, type = 'scatter', mode = 'markers', name = 'daily') %>%
add_trace(data = stock, x = ~AAPL.Close, type = 'histogram', histfunc = 'avg', xbins = list(size = "M1"),
              name = 'monthly average')


fig <- fig %>%
  layout(xaxis = list(title = 'avg of AAPL.Close',
                      zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6',
         title = 'Histogram on Date Axes',
         bargap = 0.1)
fig <- fig %>%
  layout(hovermode="x unified",
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)


fig
Click to copy
020406080100120140Jan 2015Apr 2015Jul 2015Oct 2015Jan 2016Apr 2016Jul 2016Oct 2016Jan 2017Apr 2017
dailymonthly averageHistogram on Date Axesavg of AAPL.CloseDate

Displaying Period Data

new in 4.11

If your data coded "January 1" or "January 31" in fact refers to data collected throughout the month of January, for example, you can configure your traces to display their marks at the start end, or middle of the month with the xperiod and xperiodalignment attributes. In the example below, the raw data is all coded with an X value of the 10th of the month, but is binned into monthly periods with xperiod="M1" and then displayed at the start, middle and end of the period.

library(plotly)

date = c(as.Date("2020-01-10"), as.Date("2020-02-10"), as.Date("2020-03-10"),
         as.Date("2020-04-10"), as.Date("2020-05-10"), as.Date("2020-06-10"))
value = c(1,2,3,1,2,3)

df = data.frame(date, value)

fig <- plot_ly() %>%
  add_trace(df, x = ~date, y = ~value, type = 'scatter', mode = 'lines+markers', name="Raw Data",
            marker = list(symbol="star")) %>%
  add_trace(df, x = ~date, y = ~value, type = 'scatter', mode = 'lines+markers', name="Start-aligned",
            xperiod="M1", xperiodalignment="start") %>%
  add_trace(df, x = ~date, y = ~value, type = 'scatter', mode = 'lines+markers', name="Middle-aligned",
            xperiod="M1", xperiodalignment="middle") %>%
  add_trace(df, x = ~date, y = ~value, type = 'scatter', mode = 'lines+markers', name="End-aligned",
            xperiod="M1", xperiodalignment="end") %>%
  add_trace(df, x = ~date, y = ~value, type = 'bar', name="Middle-aligned")


fig <- fig %>%
  layout(xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)

fig
Click to copy
Jan 2020Feb 2020Mar 2020Apr 2020May 2020Jun 2020Jul 202000.511.522.53
Raw DataStart-alignedMiddle-alignedEnd-alignedMiddle-aligneddatevalue

Hover Templates with Mixtures of Period data

New in v5.0

When displaying periodic data with mixed-sized periods (i.e. quarterly and monthly) in conjunction with x or x unified hovermodes and using hovertemplate, the xhoverformat attribute can be used to control how each period's X value is displayed, and the special %{xother} hover-template directive can be used to control how the X value is displayed for points that do not share the exact X coordinate with the point that is being hovered on. %{xother} will return an empty string when the X value is the one being hovered on, otherwise it will return (%{x}). The special %{_xother}, %{xother_} and %{_xother_} variations will display with spaces before, after or around the parentheses, respectively.

library(plotly)

fig <- plot_ly() %>%
  add_trace(x = c(as.Date("2020-01-01"), as.Date("2020-04-01"), as.Date("2020-07-01")),
            y = c(1000, 1500, 1700),
            type = 'bar',
            xperiod="M3",
            xperiodalignment="middle",
            hovertemplate="%{y}%{_xother}") %>%
  add_trace(x = c(as.Date("2020-01-01"), as.Date("2020-02-01"), as.Date("2020-03-01"),
                as.Date("2020-04-01"), as.Date("2020-05-01"), as.Date("2020-06-01"),
                as.Date("2020-07-01"), as.Date("2020-08-01"), as.Date("2020-09-01")),
            y = c(1100,1050,1200,1300,1400,1700,1500,1400,1600),
            type = 'scatter', mode = 'lines+markers',
            xperiod="M1",
            xperiodalignment="middle",
            hovertemplate="%{y}%{_xother}")


fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)


fig
Click to copy
Jan 2020Feb 2020Mar 2020Apr 2020May 2020Jun 2020Jul 2020Aug 2020Sep 2020Oct 2020020040060080010001200140016001800
trace 0trace 1

Time Series Plot with Custom Date Range

The data range can be set manually using layout.xaxis.range objects.

library(plotly)

stock <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

fig <- plot_ly(stock, type = 'scatter', mode = 'lines')%>%
    add_trace(x = ~Date, y = ~AAPL.High)%>%
    layout(showlegend = F, xaxis = list(range = c('2016-07-01','2016-12-31')))

fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)


fig
Click to copy
Jul 2016Aug 2016Sep 2016Oct 2016Nov 2016Dec 20169095100105110115120125130135
DateAAPL.High

Time Series With Range Slider

A range slider is a small subplot-like area below a plot which allows users to pan and zoom the X-axis while maintaining an overview of the chart. Check out the reference for more options: https://plotly.com/r/range-slider/

library(plotly)

stock <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

fig <- plot_ly(stock, type = 'scatter', mode = 'lines')%>%
  add_trace(x = ~Date, y = ~AAPL.High)%>%
  layout(showlegend = F, title='Time Series with Rangeslider',
         xaxis = list(rangeslider = list(visible = T)))
fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)


fig
Click to copy
Apr 2015Jul 2015Oct 2015Jan 2016Apr 2016Jul 2016Oct 2016Jan 201790100110120130
Time Series with RangesliderAAPL.HighDate

Time Series with Range Selector Buttons

Range selector buttons are special controls that work well with time series and range sliders, and allow users to easily set the range of the x-axis. Check out the reference for more options: https://plotly.com/r/range-slider/

library(plotly)

stock <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

fig <- plot_ly(stock, type = 'scatter', mode = 'lines')%>%
  add_trace(x = ~Date, y = ~AAPL.High)%>%
  layout(showlegend = F, title='Time Series with Range Slider and Selectors',
         xaxis = list(rangeslider = list(visible = T),
                      rangeselector=list(
                        buttons=list(
                          list(count=1, label="1m", step="month", stepmode="backward"),
                          list(count=6, label="6m", step="month", stepmode="backward"),
                          list(count=1, label="YTD", step="year", stepmode="todate"),
                          list(count=1, label="1y", step="year", stepmode="backward"),
                          list(step="all")
                        ))))
fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', margin = 0.1, width = 900)
fig
Click to copy
Apr 2015Jul 2015Oct 2015Jan 2016Apr 2016Jul 2016Oct 2016Jan 201790100110120130
1m6mYTD1yallTime Series with Range Slider and SelectorsAAPL.HighDate

Customizing Tick Label Formatting by Zoom Level

The tickformatstops attribute can be used to customize the formatting of tick labels depending on the zoom level. Try zooming in to the chart below and see how the tick label formatting changes. Check out the reference for more options: https://plotly.com/r/tick-formatting/

library(plotly)
data <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
data$Date <- as.Date(data$Date)
fig <- plot_ly(data = data, x = ~Date, y = ~mavg, type = 'scatter', mode = 'lines')%>%
  layout(xaxis = list(rangeslider = list(visible = TRUE),
                tickformatstops = list(
           list(dtickrange=list(NULL, 1000), value="%H:%M:%S.%L ms"),
           list(dtickrange=list(1000, 60000), value="%H:%M:%S s"),
           list(dtickrange=list(60000, 3600000), value="%H:%M m"),
           list(dtickrange=list(3600000, 86400000), value="%H:%M h"),
           list(dtickrange=list(86400000, 604800000), value="%e. %b d"),
           list(dtickrange=list(604800000, "M1"), value="%e. %b w"),
           list(dtickrange=list("M1", "M12"), value="%b '%y M"),
           list(dtickrange=list("M12", NULL), value="%Y Y")
         )))
fig <- fig %>%
  layout(
         xaxis = list(title = '',
                      zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(title = '',
                      zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)
fig
Click to copy
Apr '15 MJul '15 MOct '15 MJan '16 MApr '16 MJul '16 MOct '16 MJan '17 M95100105110115120125130

Hiding Weekends and Holidays

The rangebreaks attribute available on x- and y-axes of type date can be used to hide certain time-periods. In the example below, we show two plots: one in default mode to show gaps in the data, and one where we hide weekends and holidays to show an uninterrupted trading history. Note the smaller gaps between the grid lines for December 21 and January 4, where holidays were removed. Check out the reference for more options: https://plotly.com/r/reference/layout/xaxis/#layout-xaxis-rangebreaks

library(plotly)

stock <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

fig <- plot_ly(stock, type = 'scatter', mode = 'markers')%>%
  add_trace(x = ~Date, y = ~AAPL.High)%>%
  layout(showlegend = F, xaxis = list(range = c('2015-12-01', '2016-01-15')),
         title="Default Display with Gaps")

fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)


fig
Click to copy
Dec 62015Dec 13Dec 20Dec 27Jan 32016Jan 1090100110120130
Default Display with GapsDateAAPL.High
library(plotly)

stock <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

fig <- plot_ly(stock, type = 'scatter', mode = 'markers')%>%
  add_trace(x = ~Date, y = ~AAPL.High)%>%
  layout(showlegend = F, xaxis = list(range = c('2015-12-01', '2016-01-15'),
                                      rangebreaks=list(
                                        list(bounds=list("sat", "mon")), #hide weekends
                                        list(values=list("2015-12-25", "2016-01-01")))),
         title="Hide Weekend and Holiday Gaps with rangebreaks")

fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)


fig
Click to copy
Dec 72015Dec 14Dec 21Dec 28Jan 42016Jan 1190100110120130
Hide Weekend and Holiday Gaps with rangebreaksDateAAPL.High

Hiding Non-Business Hours

The rangebreaks feature described above works for hiding hourly periods as well.

library(lubridate)
library(pracma)
library(plotly)

start_date <- as.Date('2020-03-01')+hours(1)

dates <- list()

while(length(dates) < 40){
  if((as.numeric(format(start_date, format = "%H")) >= 9) & (as.numeric(format(start_date, format = "%H")) <=16)){
    dates <- c(dates, toString(start_date))
    start_date <- start_date+hours(1)
  } else {
    start_date <- start_date+hours(1)
  }
}
#dates

val <- cumsum(rand(n = 40, m = 1)[,1]) - 0.5
data <- data.frame(matrix(unlist(dates), nrow=length(dates), byrow=TRUE))
data <- cbind(data, val)
colnames(data) <- c('date', 'value')

fig <- plot_ly(data, type = 'scatter', mode = 'markers')%>%
  add_trace(x = ~date, y = ~value)%>%
  layout(showlegend = F, xaxis = list(dtick=86400000.0/2,
                                      tickformat="%H:%M\n%b\n%Y"),
         title="Default Display with Gaps"
  )

fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)

options(warn = -1)
fig
Click to copy
12:00Mar202000:00Mar202012:00Mar202000:00Mar202012:00Mar202000:00Mar202012:00Mar202000:00Mar202012:00Mar202005101520
Default Display with Gapsdatevalue
library(lubridate)
library(pracma)
library(plotly)

start_date <- as.Date('2020-03-01')+hours(1)

dates <- list()

while(length(dates) < 40){
  if((as.numeric(format(start_date, format = "%H")) >= 9) & (as.numeric(format(start_date, format = "%H")) <=16)){
    dates <- c(dates, toString(start_date))
    start_date <- start_date+hours(1)
  } else {
    start_date <- start_date+hours(1)
  }
}
#dates

val <- cumsum(rand(n = 40, m = 1)[,1]) - 0.5
data <- data.frame(matrix(unlist(dates), nrow=length(dates), byrow=TRUE))
data <- cbind(data, val)
colnames(data) <- c('date', 'value')

fig <- plot_ly(data, type = 'scatter', mode = 'markers')%>%
  add_trace(x = ~date, y = ~value)%>%
  layout(showlegend = F, xaxis = list(rangebreaks=
                                        list(
                                          list(bounds=list(17, 9),
                                        pattern="hour")),#hide hours outside of 9am-5pm
                                      dtick=86400000.0/2,
                                      tickformat="%H:%M\n%b\n%Y"),
         title="Hide Non-Business Hour Gaps with rangebreaks"
         )
fig <- fig %>%
  layout(
         xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6', width = 900)
options(warn = -1)

fig
Click to copy
12:00Mar202009:00Mar202012:00Mar202009:00Mar202012:00Mar202009:00Mar202012:00Mar202009:00Mar202012:00Mar202005101520
Hide Non-Business Hour Gaps with rangebreaksdatevalue

What About Dash?

Dash for R is an open-source framework for building analytical applications, with no Javascript required, and it is tightly integrated with the Plotly graphing library.

Learn about how to install Dash for R at https://dashr.plot.ly/installation.

Everywhere in this page that you see fig, you can display the same figure in a Dash for R application by passing it to the figure argument of the Graph component from the built-in dashCoreComponents package like this:

library(plotly)

fig <- plot_ly() 
# fig <- fig %>% add_trace( ... )
# fig <- fig %>% layout( ... ) 

library(dash)
library(dashCoreComponents)
library(dashHtmlComponents)

app <- Dash$new()
app$layout(
    htmlDiv(
        list(
            dccGraph(figure=fig) 
        )
     )
)

app$run_server(debug=TRUE, dev_tools_hot_reload=FALSE)
Click to copy