在闪亮的应用程序中更新观察器循环内的绘图 [英] Update plot within observer loop in shiny application
问题描述
我已经用R编写了一个模拟,现在我想用SHINY进行可视化。我已经将模拟的主要部分放在观察挡路中,以便进行评估。在此评估过程中,即对于每个迭代,我希望绘制当前状态。问题是我如何实现这一点,因为在我的实际代码中,绘图的呈现是在评估了主要观察者之后才执行的。例如,有没有办法暂停执行观察挡路,并在绘图更新后恢复执行?
既然我可以想象我不是唯一一个想要做这样的事情的人,难道不应该有更多的功能来解决这种情况吗?!
如果您能帮我解决这个问题,那就太好了:)
下面是服务器和UI的一些框架代码。
ui.R:
library(shiny)
shinyUI(pageWithSidebar(
headerPanel("... Simulation"),
sidebarPanel(
sliderInput("epochs",
"Number of Epochs:",
min = 1,
max = 100,
value = 10),
verbatimTextOutput("curr.iter"),
actionButton("actionB", "Action!")
),
mainPanel(
plotOutput("distPlot")
)
))
服务器.R:
library(shiny)
sinus <- data.frame()
shinyServer(function(input, output) {
dummy <- reactiveValues(iter=0)
obsMain <- observe({
for (i in 1:input$epochs) {
cat(i, " ")
x <- seq(1:input$epochs)
y <- sin(x)
sinus <<- data.frame(x, y)
dummy$iter <- i
#
# At this time I want distPlot & curr.iter to be evaluated/updated!
#
Sys.sleep(1)
}
}, suspended=TRUE)
obsAction <- observe({ if(input$actionB > 0) obsMain$resume() }) # Helps to avoid initial evaluation of obsMain...
output$curr.iter <- renderText({ as.numeric(dummy$iter) })
output$distPlot <- renderPlot({ if (dummy$iter > 1) plot(sinus, type="l") })
})
推荐答案
我对此做了更多的思考。我认为正确的解决方案是使用invalidateLater
将工作安排在小块中进行,但允许其他反应性依赖项中断我们长期运行的流程来执行更新图形等操作。
我在https://gist.github.com/trestletech/8608815整理了一个快速示例。您可以使用
运行此命令runGist(8608815)
基本前提是,我们正在执行一些长期运行的迭代计算,就像您在模拟中所做的那样,但是我们将其分成较小的块,以便允许其他反应物在其间运行。我的代码执行起来非常简单,所以我可以在大约1秒内处理100,000次循环迭代,这大约是我愿意等待应用程序交互更新的时间。我要进行500万次迭代,因此我计划发生50个块。
每次我运行100,000次迭代时,我都会更新两个反应值,它们会产生一些其他更新,这些更新最终会在renderText
中发送到我的UI(尽管像您这样的renderPlot
工作原理是一样的)。如果您运行该应用程序,您将看到,在我运行的每个块之间,在计划运行下一个块之前,这些反应都会更新。
此方法有一点开销,因此您的计算可能会稍微慢一点。但在我的机器上,在控制台上一次运行500万次迭代需要21秒,而在这种延迟分派模型中需要23秒。当然,你可以通过做更大的块来进一步降低这一点。
让我知道你的想法。我在想,把它包装起来,或者把它的一部分包含在SILINE中,或者作为扩展包包含进来,这可能是有意义的。
这篇关于在闪亮的应用程序中更新观察器循环内的绘图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!