'How to add_trace to a plotly object created from ggplotly in R

I want to be able to add a new line/trace to a plotly object. This plotly object will be created from a ggplot object using ggplotly.

I tried 1. creating the plotly object and 2. using add_trace to the plotly object, but I am unable to generate the chart.

I have used ggplot2 for a while now but am new to plotly/ggplotly.

Any help on this is appreciated please.

library(ggplot2)
library(plotly)

structure(list(Date = structure(c(1646697600, 1646784000, 1646870400, 
1646956800, 1647216000, 1647302400, 1647388800, 1647475200, 1647561600, 
1647820800, 1647907200, 1647993600, 1648080000, 1648166400, 1648425600, 
1648512000, 1648598400, 1648684800, 1648771200, 1649030400, 1649116800, 
1649203200, 1649289600, 1649376000, 1649635200, 1649721600, 1649808000, 
1649894400, 1649980800), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    PolicyRate = c(0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 
    0.375, 0.375, 0.375, 0.375, 0.375, 0.375, 0.375, 0.375, 0.375, 
    0.375, 0.375, 0.375, 0.375, 0.375, 0.375, 0.375, 0.375, 0.375, 
    0.375, 0.375, 0.375, 0.375, 0.375), USGG1y = c(1.0522, 1.096, 
    1.1063, 1.0907, 1.2092, 1.1937, 1.1989, 1.1911, 1.1755, 1.2477, 
    1.3147, 1.4839, 1.5409, 1.629, 1.6627, 1.647, 1.5951, 1.595, 
    1.6649, 1.6675, 1.7168, 1.7245, 1.6933, 1.7347, 1.7528, 1.6567, 
    1.6566, 1.6979, 1.6979), USGG2y = c(1.601, 1.682, 1.698, 
    1.75, 1.863, 1.852, 1.941, 1.917, 1.939, 2.118, 2.167, 2.099, 
    2.141, 2.273, 2.331, 2.368, 2.309, 2.337, 2.459, 2.424, 2.517, 
    2.473, 2.463, 2.516, 2.502, 2.407, 2.351, 2.456, 2.456), 
    USGG5y = c(1.778, 1.88, 1.925, 1.948, 2.092, 2.107, 2.182, 
    2.145, 2.144, 2.323, 2.4, 2.32, 2.399, 2.546, 2.558, 2.5, 
    2.44, 2.462, 2.56, 2.552, 2.697, 2.683, 2.709, 2.756, 2.791, 
    2.69, 2.654, 2.788, 2.788), USGG10y = c(1.848, 1.955, 1.99, 
    1.995, 2.135, 2.146, 2.188, 2.173, 2.152, 2.292, 2.384, 2.294, 
    2.374, 2.477, 2.461, 2.397, 2.352, 2.341, 2.385, 2.398, 2.549, 
    2.6, 2.66, 2.705, 2.782, 2.724, 2.702, 2.829, 2.829), USGG30y = c(2.229, 
    2.337, 2.369, 2.356, 2.473, 2.479, 2.455, 2.471, 2.423, 2.519, 
    2.603, 2.486, 2.541, 2.587, 2.542, 2.503, 2.477, 2.45, 2.434, 
    2.458, 2.574, 2.628, 2.681, 2.72, 2.811, 2.813, 2.814, 2.918, 
    2.918)), row.names = c(NA, -29L), class = "data.frame")

g <- data %>% ggplot() +
     geom_line(aes(x=Date, y=USGG2y))

g
p <- ggplotly(g)
p # works fine until here.

p1 <- p %>% add_trace(x=~Date, y=~USGG5y,yaxis = "y2", mode="lines+markers",type = "scatter")
#doesnt throw up any obvious error"

p1 #this one gives me a blank plotly chart"


Solution 1:[1]

This one took a while.

Plotly's interpretation (or ggplot2's delivery) was rendered as if the dates were character fields; the axis tick labels were literal labels. The plot wouldn't render because it presented more of a picture of what ggplot2 created than a graph.

The way forward

  • change the x data for the trace to date type data
  • update the axes to hold values instead of labels
  • add the new trace

There are a few different ways that would work to accomplish this. I've only provided one method.

After creating your ggplotly object, update the object. The easiest way to do this is by adding the exact same data from your data frame.

p = ggplotly(g)
p[["x"]][["data"]][[1]][["x"]] <- data$Date # change the 'type'

With the axes, you could update the object or assign new settings. This method assigns some new settings. Lastly, add the new trace.

p %>% layout(yaxis = list(range = c(0, 3), tickmode = "auto"),
             xaxis = list(range =  c(data$Date[1], data$Date[nrow(data)]),
                          tickformat = "%b %d", type = "date", 
                          tickmode = "auto")) %>% 
  add_lines(x = ~Date, y = ~USGG5y)

That's it. A few notes on what I did here first...

  • range sets the lower and upper limit
  • tickmode has three options
    • it is set toarray when you use labels
    • I changed it to auto (the labels are ignored)
  • for the x-axis, that range equates to the min/max dates in date type format
  • tickformat:
    • %b is d3 coding for the abbreviated month name
    • %d is the day of the month without padding (i.e., Mar 1 versus Mar 01 for March 1st.)
    • there's a space between the two, so that there's a space between the month and day on the axis

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1