我想了解为什么在observeEvent()
内部使用invalidateLater()
时不会自动更新下表。我已经准备了以下程序来说明我的问题,"mytable2"使用reactiveTimer()
,并且确实产生了所需的输出,但是"mytable"使用invalidateLater()
,并且除非我单击"更新"按钮,否则不会自动更新。为什么?
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("update", "Update")
),
mainPanel(
column(6, tableOutput('mytable')),
column(6, tableOutput('mytable2'))
)
)
)
server <- function(input, output) {
values <- reactiveValues(df = RenderMyTable())
observeEvent(invalidateLater(1000), {
values$df <- RenderMyTable() # This does not update after 1 sec
})
observeEvent(input$update, {
values$df <- RenderMyTable() # This does update upon clicking
})
output$mytable <- renderTable(values$df) # Depends on reactiveValues
autoInvalidate <- reactiveTimer(1000)
output$mytable2 <- renderTable({
autoInvalidate()
RenderMyTable() # >This does update after 1 sec
})
}
time1 <- Sys.time() # Start time
df <- data.frame(a = 1:1000) # Some data
RenderMyTable <- function(){
# Seconds since start time
time2 <- as.integer(difftime(Sys.time(), time1, units="secs"))
df.now <- df[1:time2,] # Updates each second
df.now
}
shinyApp(ui = ui, server = server)
后续问题
此外,让情节自动更新的合适方法是什么(就像"mytable2"一样(?到目前为止,我更新绘图的唯一方法是使用上面"mytable"中的"更新"按钮,但我希望它在1秒后自动更新,因为每秒钟都有新数据开始添加到绘图数据表中。
如能提供任何建议或资源,我们将不胜感激。
首先,我想说,我从这段代码中学到了一些东西,这是一种非常巧妙的自动化绘图更改的方法,所以谢谢你,我将来也会使用它。
对于您的问题,我已经研究了invalidateLater
,它是由反应和观察函数组成的,正如您所研究的那样。只需将observeEvent
更改为observe
,并将invalidateLater
函数移动到代码的主块中,而不是将其作为参数传递,就可以在第一个表输出中解决此问题。
以下是我从中获得想法的工作版本的链接:闪亮-无效后期
对于您的后续问题,我们可以通过与以前完全相同的过程来完成:
output$autoupdate_plot <- renderPlot({
invalidateLater(2000)
hist(rnorm(isolate(RenderMyTable())))
})
现在将等待2秒钟,然后再运行该功能。当值发生变化时,我们使用isolate
来避免更新,但只有当我们决定时才更新,在这种情况下是在2秒的间隔上。
下面的完整代码是您非常创新的工作的扩展:
app.R
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("update", "Update")
),
mainPanel(
column(4, tableOutput('mytable')),
column(4, tableOutput('mytable2')),
column(4, plotOutput("autoupdate_plot"))
)
)
)
server <- function(input, output) {
values <- reactiveValues(df = RenderMyTable())
observe({
invalidateLater(1000)
values$df <- RenderMyTable() # This does not update after 1 sec
})
observeEvent(input$update, {
values$df <- RenderMyTable() # This does update upon clicking
})
output$mytable <- renderTable(values$df) # Depends on reactiveValues
autoInvalidate <- reactiveTimer(1000)
output$mytable2 <- renderTable({
autoInvalidate()
RenderMyTable() # >This does update after 1 sec
})
output$autoupdate_plot <- renderPlot({
invalidateLater(2000)
hist(rnorm(isolate(RenderMyTable())), main = "Auto Hist")
})
}
time1 <- Sys.time() # Start time
df <- data.frame(a = 1:1000) # Some data
RenderMyTable <- function(){
# Seconds since start time
time2 <- as.integer(difftime(Sys.time(), time1, units="secs"))
df.now <- df[1:time2,] # Updates each second
df.now
}
shinyApp(ui = ui, server = server)