Search code examples
rshinydygraphsshinyjsr-dygraphs

How to align the x-axis of synchronized R dygraphs with single and double y-axis?


My goal is to write a Shiny app to visually compare multiple time series. All time series have the same range of x-values. Vertically stacked and synchronized dygraphs nicely show the y-value of individual time series for a common x-value.

This approach works if all dygraphs only have one y-axis (i.e. no "y2" axis):

library(shiny)
library(dygraphs)

ui <- fluidPage(
  mainPanel(
    dygraphOutput("one_axis"),
    dygraphOutput("two_axis")
  )
)

server <- function(input, output) {
  output$one_axis <- renderDygraph({
    dygraph(fdeaths, group = "foo")
  })
  output$two_axis <- renderDygraph({
    dygraph(mdeaths, group = "foo")
  })
}

shinyApp(ui, server)

the x-axis ticks are vertically aligned

In my use case some dygraphs have two y-axis: "y" and "y2". The x-axis of the plot with the double y-axis get squashed to make space for the "y2" axis and labels:

library(shiny)
library(dygraphs)

ui <- fluidPage(
  mainPanel(
    dygraphOutput("one_axis"),
    dygraphOutput("two_axis")
  )
)

server <- function(input, output) {
  output$one_axis <- renderDygraph({
    combined <- cbind(mdeaths, fdeaths)
    dygraph(combined, group = "foo") %>% 
      dySeries("mdeaths", axis = "y") %>% 
      dySeries("fdeaths", axis = "y2")
  })
  output$two_axis <- renderDygraph({
    dygraph(mdeaths, group = "foo")
  })
}

shinyApp(ui, server)

the x-axis ticks are no longer aligned

Question:

Is there a way to align the x-axis of all dygraphs, regardless of whether they have one or two y-axis?

Things I tried without success:

  • adding two y-axis for a single variable
  • playing with dyOptions(rightGap)

I found a similar question but I'm not familiar with javascript.

edit: typo


Solution

  • I got this working using this code (this is Javascript but perhaps there is something analogous in R):

    // Find our max graph width (finding min doesn't work because dygraph clips its canvases)
    var maxWidth = 0;
    for (graph of graphs) {
        maxWidth = Math.max(maxWidth, graph.plotter_.area.w);
    }
    // Use a negative rightGap to make all graphs match the max width
    for (graph of graphs) {
        graph.updateOptions({rightGap: graph.plotter_.area.w - maxWidth});
    }
    

    I don't love it for a number of reasons:

    • It's using the private .plotter_ variable
    • It's using a negative rightGap to align things (I tried using a positive rightGap to shrink graphs to the min size, but I think Dygraph clips its canvases so it never erased the right side of the wider graphs when I shrunk them)
    • The legends don't appear in the right spot for graphs that I expand

    I'm on Dygraph 2.0.0 so maybe this is easier in the latest version. Anyway I hope this helps - I had the exact same problem and it got me by for now!