Change limits for a plot on a click in another plot in R

Viewed 239

I need to have two plots displayed. The first plot is the main scatter plot. And the second plot must be changed each time one clicks a point in the first plot. So I need the behavior similar to the picture at https://davidgohel.github.io/ggiraph/index.html

To be more precise, each point of the first plot must be associated with the x-limits of the second plot.

I have found a corresponding example How to display many points from plotly_click in R Shiny? and modified it accordingly

library(ggplot2)
library(plotly)
library(shiny)

ui <- fluidPage(
  plotlyOutput("plot1"),
  plotlyOutput("plot2")
)

range2=1000000
p1x=runif(10)
p1y=runif(10)
p1t=runif(10)*range2

times=seq(1,range2)
#ys=cumsum(rnorm(range2)/sqrt(range2))
ys=runif(range2)


plot2xlim=c(1000,2000)
p2 <- plot_ly()
p2 <- add_trace(p2, x = times, y = ys, type = "scattergl", mode = "lines",
                line = list(width = 1, color = "blue"))

server <- function(input, output, session) {
  # make plotly plot
  output$plot1 <- renderPlotly({
    g <- ggplot()+geom_point(aes(x=p1x,y=p1y))
    ggplotly(g)
  })
  output$plot2 <- renderPlotly({
    selpoint <- event_data("plotly_click")$pointNumber[1]+1
    plot2xlim <- c(p1t[selpoint]-500,p1t[selpoint]+500)
    p2 <<- layout(p2, xaxis = list(range = plot2xlim), 
                  yaxis = list(range = c(0, 1)))
    p2
  })
}
shinyApp(ui, server)

However the code works very-very slowly, since plot2 is built for a huge data. So it takes much time to rebuild it.

Is there a way not to redraw the second plot on each click, but just to change its x-limits?

2 Answers

Seems like there is no way to get around this, as every change/query in the graph implies a re-rendering of the graph, ever since Shiny sends new data to the second graph every time a data point is clicked on the first graph.

This isn't exactly what you asked, but...

We can build a plotly object with an x-axis slider in it. The redraw isn't instant but it's much faster than reloading in the subset of data afresh each time you want to change the range.

library(ggplot2)
library(plotly)

range2=1000000
p1x=runif(10)
p1y=runif(10)
p1t=runif(10)*range2
times=seq(1,range2)
ys=runif(range2)

# Put the data in a data frame
data <- data.frame(x = times, y = ys)

# Use ggplotly to take a ggplot object and covert it to plotly
p2 <- ggplot(data, aes(x = x, y = y)) + geom_line() 
ggplotly(p2) %>% rangeslider()
Related