想要在 R Shiny 中显示 for 循环图的所有变化(重叠)



这是关于Rshiny的询问。我创建了一个名为foo的函数,如下所示。在函数中,for 循环中有 5 个图。在 Shiny 中制作绘图时,只有最后一个绘图可见,其余绘图不可见。您看不到正在创建(更新(五个图吗?

foo <- function(iter = 5){
  for(j in 1:iter){
    plot(iris$Sepal.Length, iris$Sepal.Width, col = j)
    Sys.sleep(0.5)
  }
}
ui<-shinyUI(fluidPage(
sth 
 plotOutput('myplot')
))
server <- shinyServer(function(input, output, session){
sth ...
 output$myplot <- renderPlot({
     f <- foo(iter = 3)
    })  
 })
})

不能在此处使用循环,因为服务器在 UI 中呈现新输出之前执行所有代码,Sys.sleep()只会导致整个 R 进程停止指定的时间量。相反,您可以使用invalidateLater()使绘图函数以设定的时间间隔触发,同时仍允许程序的其余部分正常运行。

library(shiny)
ui <- shinyUI(fluidPage(
  sliderInput("iterations", "Iterations", 1, 10, 3),
  sliderInput("interval", "Interval (ms)", 100, 1000, 500, step = 100),
  actionButton("draw", "Draw"),
  plotOutput('myplot')
))
server <- shinyServer(function(input, output, session) {
  foo <- function(iterations = 5, interval = 500) {
    i <- 0
    output$myplot <- renderPlot({
      i <<- i + 1
      if (i < iterations)
        invalidateLater(interval)
      plot(iris$Sepal.Length, iris$Sepal.Width, col = i)
    })
  }
  observeEvent(input$draw, foo(input$iterations, input$interval))
})
shiny::shinyApp(ui, server)

现在,你也可以把每个间隔做一些事情的想法包装成一种延迟map函数,看起来像这样:

map_later <- function(.x, .f, ..., .interval = 500) {
    i <- 0
    observe({
      i <<- i + 1
      if (i < length(.x))
        invalidateLater(.interval)
      .f(.x[i], ...)
    })
}

这将产生一个更整洁、更易于管理的服务器:

ui <- shinyUI(fluidPage(
  plotOutput('myplot')
))
server <- shinyServer(function(input, output, session) {
  map_later(1:5, function(i) {
    output$myplot <- renderPlot({
      plot(iris$Sepal.Length, iris$Sepal.Width, col = i)
    })
  }, .interval = 500)
})
shiny::shinyApp(ui, server)

命名在这里可能不是很好,但是嘿,它做了它应该做的事情。

最新更新