强制Shiny在循环中渲染图表

3

我有一个运行模拟的闪亮应用程序。目标是以绘图的形式向用户显示计算步骤。

如何让shiny强制更新绘图?

最小工作示例(MWE)如下所示:

library(shiny)

server <- function(input, output, session) {
  # base plot as a placeholder
  output$myplot <- renderPlot(plot(1:1, main = "Placeholder"))

  # wait until the button is triggered
  observeEvent(input$run, {
    print("Do some calculations in 3 steps")
    for (i in seq_len(3)) {
      print("Do some calculations")
      # ...
      x <- seq_len(i * 100)
      y <- (x + 1)^2 - 1 # this will do for now

      print("Plot the data ")

      # ISSUE HERE!
      # this should render the current step of the simulation, instead it 
      # renders only after the whole code is run (i.e., after step 3)
      output$myplot <- renderPlot(plot(x, y, main = sprintf("Round %i", i), type = "l"))

      print("Wait for 1 second for the user to appreciate the plot...")
      Sys.sleep(1)
    }
  })
}

ui <- fluidPage(
  actionButton("run", "START"),
  plotOutput("myplot")
)

shinyApp(ui = ui, server = server)

问题在于,shiny运行代码并在模拟结束时生成一个图表,但我想在每个模拟步骤(至少显示一秒钟)获得一个图表。
非常感谢您的任何帮助/提示。
附录
我看了这个帖子,但用一个图表/renderPlot替换文本并不会产生正确的结果。

你需要循环UI和服务器的输出以适应每个图。你不能只有一个图形输出变量并期望循环产生多个图形。 - Ryan Morton
@RyanMorton 你手头有例子吗? - David
尝试添加一个滑块输入,如下所示:sliderInput("format", "自定义格式:", min = 0, max = 3, value = 0, step = 1, animate = TRUE) - CCurtis
1个回答

5

您可以将observer嵌套到observeEvent中,以使其能够正常工作。这是基于Jeff Allen在您提供的SO主题中的代码。

关键部分:

observeEvent(input$run, {
    rv$i <- 0
    observe({
      isolate({
        rv$i <- rv$i + 1
      })

      if (isolate(rv$i) < maxIter){
        invalidateLater(2000, session)
      }
    })
  })

完整代码:

library(shiny)

server <- function(input, output, session) {
  rv <- reactiveValues(i = 0)
  maxIter <- 3

  output$myplot <- renderPlot( {
    if(rv$i > 0) {
      x <- seq_len(rv$i * 100)
      y <- (x + 1)^2 - 1 # this will do for now
      plot(x, y, main = sprintf("Round %i", rv$i), type = "l") 
    } else {
      plot(1:1, main = "Placeholder")
    }
  })

  observeEvent(input$run, {
    rv$i <- 0
    observe({
      isolate({
        rv$i <- rv$i + 1
      })

      if (isolate(rv$i) < maxIter){
        invalidateLater(2000, session)
      }
    })
  })

}

ui <- fluidPage(
  actionButton("run", "START"),
  plotOutput("myplot")
)

shinyApp(ui = ui, server = server)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接