Dynamically Adding Lines to a Plotly Plot in R

Since Plotly made their interactive graphing platform available for R, I’ve been trying to incorporate it into more of my projects. Recently I was working on a graph that included the price of a particular stock as well as multiple moving averages and thought it could be useful to use vertical lines to help better define buy and sell points for the viewer. While ggplot2 allows users to pass a single vector of values into the geom_vline() argument to do this, Plotly appears to require a separate list of arguments for each line (possibly as a result of the complete control they give you over the positioning of shapes). Below is a snippet of the data I used to build the graph. Full data available here.

A snapshot of the full GE price dataset

Below is an example of the arguments necessary to build a vertical line from the x axis to the adjusted price for GE on 2–11–1997.

p <- layout(p, shapes  = list(type = “line”, fillcolor = “blue”, 
line = list(color = “blue”),
opacity = 0.3,
x0 = “1997–02–11”,
x1 = “1997–02–11”,
xref = “x”,
y0 = 0,
y1 = 10.22,
yref = “y”))

Obviously drawing more than a couple lines in this manner would be very clumsy. My goal was to point out crossover points between the 2 EMAs, which means a non-programmatic approach would be very impractical. To make this task easier, I created a simple “for” loop to identify crossovers indicating a “buy” (in green) or a “sell” (in red).

First I used dplyr to filter out all the days where the EMAs did not cross:

line_dat <-
dat %>%
filter(dat$signal != '--')

Then I created a list of lists, with each of the nested lists containing the arguments for one line. To make it easier for the end user to distinguish between “buy” and “sell” days, I used an if-else statement to alter the line color for each iteration depending on the signal.

line_list <- list()
for(i in 1:nrow(line_dat)){
line_color <- ifelse(line_dat$signal[i] == 'buy','green','red')
line_list[[i]] <-
list(type = “line”,
fillcolor = line_color,
line = list(color = line_color),
opacity = 0.3,
x0 = line_dat[[1]][i],
x1 = line_dat[[1]][i],
xref = “x”,
y0 = 0,
y1 = line_dat[[2]][i],
yref = “y”)

Below is the resulting graph

Click here for the interactive version

I’ve already found other uses for Plotly at work, and I’m excited to see how I can work it into my R workflow.