我有一个运行模拟的 Shiny 应用程序。目标是以图表的形式向用户展示中间的计算步骤。
我如何强制 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 运行代码并在模拟结束时生成一个图,但是,我想在每个模拟步骤中得到一个图(至少显示一秒钟)。
非常感谢任何帮助/提示。
附录
我看过这个post , 但用 plot/renderPlot
替换文本不会产生正确的结果。
最佳答案
您可以将 observer
嵌套到 observeEvent
中以使其工作。基于您链接的 SO 主题中 Jeff Allen 的代码。
关键部分:
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)
关于r - 强制 Shiny 以循环渲染图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47270540/