如何提高 dygraph 在 shiny 中的刷新率?

问题描述 投票:0回答:1

我想使用一个闪亮的应用程序和 dygraphs 来浏览一个时间序列(有很多点,这里是 2E6)。 下面的脚本是一个最小的例子,除了数字输入

start
的变化导致显示冻结 5 秒外,它工作得很好。相比之下,使用范围选择器移动几乎没有延迟。所以我想这应该是可行的,但我没有运气解决这个问题。

有什么办法可以改善吗?

library(shiny)
library(dygraphs)

ui <- fluidPage(
  # Sidebar
  sidebarLayout(
    # Sidebar panel for inputs ----
    sidebarPanel(
    numericInput("start", label = "Start (iteration)", 
                   value = 1, step = 5E4),
    numericInput("duration", label = "Duration (iterations)", 
                 value = 5E4)
    ),
  # Main    
  mainPanel(
      dygraphOutput("plot")
    )
  )
)

server <- function(input, output) {
  z<-rnorm(2E6,1,10) # data
  time<-1:length(z)
  df<-data.frame(time,z)
  output$plot <- renderDygraph({
    dygraph(df) %>% dyRangeSelector(dateWindow = c(input$start,input$start+input$duration) ) 
  })
  
}
shinyApp(ui = ui, server = server)

r shiny dygraphs
1个回答
1
投票

此行为的原因是每当您更改

input$start
(
input$duration
) whole plot 重新渲染。当您简单地更改选择器手柄时,
dygraph
确保显示相关数据,无需 重新渲染整个图形(这实际上是 dygraph 的功能之一)。

您可以借助一些 JavaScript 来实现这种行为。思路如下:

  1. 在您的

    renderDygraph
    函数中,您不依赖于
    input$start
    input$duration
    )。这避免了当其中一个值发生变化时重新渲染整个图形。

  2. 你包含一个

    observer
    ,它调用 dygraph JavaScript 函数
    updateOptions
    ,它反过来更新 x 轴上的可见范围(因此基本上与手动更改范围手柄相同)。

  3. 为此,您需要:

    1. 在渲染时存储 dygraph 对象(我们使用
      htmlwidgtes::onRender
      来表示),这样我们就可以稍后调用
      updateOptions
    2. 添加自定义消息处理程序,从 shiny 调用 JavaScript(您也可以使用
      shinyjs
      为您封装它)。

代码千言万语,下面是一个有效的例子:

library(shiny)
library(dygraphs)
library(htmlwidgets)

ch <- JS("
   var plots = [];
   Shiny.addCustomMessageHandler('adjust-x-axis', function(limits) {
     const dg = plots['plot'];
     if (dg) {
       dg.updateOptions({dateWindow: [limits.xmin, limits.xmax]});
     }
   });")

ui <- fluidPage(
   # Sidebar
   sidebarLayout(
      # Sidebar panel for inputs ----
      sidebarPanel(
         numericInput("start", label = "Start (iteration)", 
                      value = 1, step = 5E4),
         numericInput("duration", label = "Duration (iterations)", 
                      value = 5E4)
      ),
      # Main    
      mainPanel(
         tags$head(
           tags$script(
              ch,
              type = "text/javascript"
           ) 
         ),
         dygraphOutput("plot")
      )
   )
)



server <- function(input, output, session) {
   z <- rnorm(2E6, 1, 10) # data
   time <- 1:length(z)
   df <- data.frame(time, z)
   output$plot <- renderDygraph({
      dygraph(df) %>% 
         dyRangeSelector(dateWindow = c(1, 1 + 5E4)) %>% 
         onRender("function(el, x) {
           plots['plot'] = this.dygraph;
         }")
   })

   observe({
      start <- req(input$start)
      duration <- req(input$duration)
      session$sendCustomMessage(
         "adjust-x-axis", 
         list(xmin = start, xmax = start + duration)
         )
   })
}

shinyApp(ui = ui, server = server)
© www.soinside.com 2019 - 2024. All rights reserved.