I am trying to automate the interaction of a Shiny app so it displays a series of results while incrementing through a predetermined range of inputs, without having to repetitiously count and change input values. This automation will provide a systematic view of a set of inputs, such as displays of refreshed price charts for selected stocks, or plots of current performance indicators for real-time processes that are being monitored.
This is similar to question [Update graph/plot with fixed interval of time] (Update graph/plot with fixed interval of time) which runs a loop with a timer. Extending that approach, my objective is to: a) Automatically set the invalidateLater pause high (1 hour) to effectively stop the cycle after a fixed (5) set of displays, pending new user input to restart it.
b) [When I can do that, I will add a counter-based control to cycle through a set of input$obs before it stops. For simplicity, that step, which has the same error and presumably same solution, is omitted here.]
Using the above referenced toy example, the following script does repeatedly cycle through its 5 displays, but it yields this error rather than changing the pause interval.
Listening on port 8100 Error in hist.default(dist, main = paste("Last Histogram count =", as.numeric(updater()), : 'x' must be numeric
as.numeric(autoControl()) Error: could not find function "autoControl"
I can not find the reactive conductor, reactiveValues or other methods that this task requires. Thank you for your help.
library(shiny)
updates <- 0
updater <- function(){ updates + 1 }
runApp(list(
ui = pageWithSidebar(
headerPanel("Hello Shiny!"),
sidebarPanel(
sliderInput("obs",
"Number of observations:",
min = 1,
max = 1000,
value = 50)
,
selectInput(inputId = "secPause",
label = "Seconds between displays:",
choices = c(1, 2, 3, 60*60),
selected = 2)
),
mainPanel(
plotOutput("distPlot")
)
),
server =function(input, output, session) {
updateTracker <- reactive( {
invalidateLater(as.numeric(input$secPause) * 1000, session)
updates <<- as.numeric(updater())
})
autoControl <- reactive( {
if(updateTracker() <= 5)
secPause <<- input$secPause
else
secPause <<- 60*60
return(secPause)
})
output$distPlot <- renderPlot( {
if(updateTracker() <= 5) {
# generate an rnorm distribution and plot it
dist <- rnorm(input$obs)
hist(dist, main = paste("Histogram count =" , updateTracker()))
}
else {
updates <<- 0
hist(dist, main = paste("Last Histogram count =",
as.numeric(updater()), "with secPause =",
as.numeric(autoControl())))
}
})
}
))
You are getting the error because the
hist
distribution is defined inside the if clause, but you are using it (after 5 intervals) inside theelse
clause, where it is not defined. That's why it works for the first 5 intervals.After I moved the dist to before the
if
condition, I got your cycling to work. (I also split your code into UI.R and server.R to make it more manageable.) Not pasting here since it is essentially the same code, but you can find the working version of code in this gist.