R Shiny application: Modifying plot without re-ren

2019-05-15 00:35发布

问题:

I've been looking into ways to update a plot within an R Shiny application without having to re-render the whole plot. I'm working with temporal data which is animated via a Slider Input (animationOptions(playButton = TRUE)). The idea is to somehow highlight the part of the plot which is selected via the Slider Input. Re-rendering the whole plot at every animation step would make the whole application uselessly slow.

The most elegant solution with ggplot2 would have been, if shiny offered a way to add layers to the ggplot (e.g. + geom line()) and integrated this layer seamlessly into the plot without re-rendering it. Sadly, this does not seem to work. A bit of a hack could include creating a second ggplot-instance with exactly the same x/y-dimensions and overlapping the two plots.

EDIT: I've just learnt that there are more javascript oriented plotting methods than ggplot2. For example, using dygraphs and adding a layer of dyShading, the selected area gets highlighted nicely. The basic question remains the same though, since changing the start- and end values of dyShading() seems to require re-rendering the whole plot.

library(shiny)
library(dygraphs)
library(xts)


data <- data.frame(
  datetime = as.POSIXct("2016-06-20 17:00:00", tz = "UTC") + 1:100*60,
  y = rnorm(100)
)

data_xts <- as.xts(data[,-1], data[,1])

minDatetime <- min(data$datetime)
maxDatetime <- max(data$datetime)
minY = min(data$y)
maxY = max(data$y)
plotlimits <- lims(x = c(minDatetime, maxDatetime), y = c(minY, maxY))


ui <- fluidPage(
  sliderInput("timeslider", "Time Slider",
              min = minDatetime,
              max = maxDatetime,
              value = c(minDatetime, minDatetime+10*60),
              animate = animationOptions(interval=200)
              ),
  dygraphOutput("dyplot")
)

server <- function(input, output) {

  data_fil <- reactive({
    data[data$datetime <= input$timeslider[2] & data$datetime >= input$timeslider[1],]
  })

  output$dyplot <- renderDygraph({
    dygraph(data_xts) %>%
      dyShading(
        from = as.character(input$timeslider[1]), 
        to = as.character(input$timeslider[2]),
        color = "tomato")
  })

}

shinyApp(ui = ui, server = server)