Use isolate() with actionButton or not?

845 views
Skip to first unread message

Tingolfin

unread,
Nov 28, 2016, 5:55:17 AM11/28/16
to Shiny - Web Framework for R

In my shiny app, users give a year, date and weather station of which they want temperature data. Then they click an action button which generates a plot based on a selection of data according to the input.
I used to have no action button, but with each change in input the plot was remade and it all went extremely slow. I also got an error message which showed for 2 secs before the plot appeared. Sometimes first an empty plot showed for a few secs and then the right plot appeared. Lots of weird and slow stuff, so I decided to let the effect of changed input be delayed until a button is clicked.

In my server part of the app, the code for the plot before I had the button looked like this:
output$plotTemp <- renderPlot({
  importdata
(input$jaartal)
  weerstation
<- which(weerstations == input$weerstation)
  temperatuur
(input$datums, weerstation)
})

importdata() and temperatuur() are functions I import via source(script.R) at the start of the app. They import and calculate temperature data and temperatuur() creates a ggplot at the end.

When I inserted the action button, called "button", the code looked like this:
inputJaar <- eventReactive(input$button, {input$jaartal})
inputDatum
<- eventReactive(input$button, {input$datums})
inputStation
<- eventReactive(input$button, {
  weerstation
<- which(weerstations == input$weerstation)
})
output$plotTemp
<- renderPlot({
  importdata
(inputJaar())
  temperatuur
(inputDatum(), inputStation())
})
I'm not sure if this is proper/clean programming. I have little experience and never used actionButton() before. All I know is that things still go very slow, but at least it doesn't recalculate with every change in input. Also the error or empty plot that showed for a few secs never appear again. That's a good start.

When I asked someone if it was possible to speed things up (or have cleaner code) they told me to use isolate(). I read help pages, saw a youtube video and read some blogs. But I can't grab the difference with my current code (except that it's shorter). Anyway, the code with isolate looks like this:
output$plotTemp <- renderPlot({
  input$button
  isolate
({
    importdata
(input$jaartal)
    weerstation
<- which(weerstations == input$weerstation)
    temperatuur
(input$datums, weerstation)
 
})
})
I don't notice any changes in speed. The plot still only changes after I click the button, but the error that appeared a few secs before the plot in my first version now appears when I open the plot. It dissapears after I click the button. I don't want my users to see an error at the start, they'll think it's not working.
The error says: "x must be of length 1 or 2". I tried to understand en avoid this before I came up with the actionbutton solution, but never found it.
Anyway, with the button but without isolate, it doesn't show, so I started to ignore it...

What's the difference between the 2nd and 3rd code? An explanation "for dummies" about using isolate or not with the actionbutton would also be very welcome.
Any other solutions or tips to improve my code? (good programming practices or so :) )

Thanks in advance!
Message has been deleted

Tingolfin

unread,
Nov 28, 2016, 5:58:14 AM11/28/16
to Shiny - Web Framework for R
Forgot to translate, but input$jaartal is the input of year. Given with selectInput. input$datums gives a date range, chosen via dateRangeInput and input$weerstation gives the weather station, also chosen via selectInput.

Joe Cheng [RStudio]

unread,
Nov 29, 2016, 8:13:01 PM11/29/16
to Shiny - Web Framework for R
Either way is perfectly fine, whichever seems more intuitive to you.

If you want your isolate() code to not throw an error, replace this line:

input$button

with this:

req(input$button)

This will have the effect of cancelling the plot if the button has never been pressed (as is the case when your app first loads). See http://shiny.rstudio.com/articles/req.html for more info.

Tingolfin

unread,
Dec 1, 2016, 7:18:55 AM12/1/16
to Shiny - Web Framework for R
Thanks for the reply! The req() made my day by the way.

I encountered another problem as I continued working on my app. I'm not sure if I'm allowed to post it here, if not I'll make a new discussion.
If prefered not using isolate(), but now it seems I have to.

My app is slow and I want people to know it's working, so I want to add gifs to the button like this: https://github.com/daattali/advanced-shiny/tree/master/busy-indicator
With the separate reactive events (see code original question) the gifs reappear and disappear with each step and they have to stay during the whole actionButton process.
With isolate(), this is the case.

Now I have 2nd plot in my app, which also appears after the first button click (1). But it uses an extra input: species. This plot has to adjust immediately when the species input changes (2), but only after a button click when date or station input changes (3).

After many trials en reordering things soo many times, requirements (1) and (2) are fullfilled, but (3) isn't. The plot does not adjust without a click when the station input changes (= good), but it does change immediately when the date input is changed (= not good).
This is the code I got now:
output$plotSoort <- renderPlot({
    req
(input$button)

    isolate
(
      importdata
(input$jaartal)
      weerstation
<- which(weerstations == input$weerstation)
      temperatuur
(input$datums, weerstation)})

   
if(input$populatie == "PER"){            
      perenbladvlo
(input$datums, weerstation)
   
}                                        
   
else if(input$populatie == "OOR"){
      oorworm
(input$datums, weerstation)
   
}
   
else if(input$populatie == "FLU"){
      fluweelmijt
(input$datums, weerstation)
   
}
 
})

How can I delay the reaction on date changes? Or where to put isolate() exactly?
Reply all
Reply to author
Forward
0 new messages