How to execute a function in R Shiny after getting arguments from selectInput or sliderInput and clicking on ActionButton?

Viewed 36

So my function takes arguments from selectInput and sliderInput. After I click the button GO! it starts and generates the plot. After I use the slider to change the value it starts again, even without clicking on the button. How do I change it so it doesn't start without me clicking on the button? I don't want it to execute instantly while I'm still using the slider. I'm sorry if it's a stupid question, I'm a total beginner with shiny!

pageWithSidebar(
  headerPanel('Algorytm genetyczny - optymalizacja funkcji Levy13'),
  sidebarPanel(
    selectInput('type_of', 'Typ algorytmu', choices = c("real-valued", "binary"), multiple = FALSE),
    sliderInput('pop', 'Wielkosc populacji', min = 50, max = 1000, value = 100, step = 50, round = TRUE,
                animate = TRUE, width = '400px'),
    sliderInput('epoch', 'Liczba iteracji', min = 100, max = 2000, value = 1000, step = 100, round = TRUE,
                animate = TRUE, width = '400px'),
    actionButton("goButton", "Go!", class = "btn-success"),
  ),
  mainPanel(
    plotOutput('plot1'),
    plotOutput('plot2'),
    plotOutput('plot3')
  )
)
library(GA)
library(tidyverse)
library(ranger)
library(caret)
library(tictoc)

function(input, output, session) {
  
  
  levy13 <- function(x1, x2)
  {
    term1 <- (sin(3*pi*x1))^2
    term2 <- (x1-1)^2 * (1+(sin(3*pi*x2))^2)
    term3 <- (x2-1)^2 * (1+(sin(2*pi*x2))^2)
    
    y <- term1 + term2 + term3
    return(y)
  }
  
  x1 <- x2 <- seq(-10, 10, by = 0.1)
  f <- outer(x1, x2, levy13)
  
  output$plot1 <- renderPlot(persp3D(x1, x2, f, theta = 50, phi = 20, col.palette = bl2gr.colors) )
  
  output$plot2 <- renderPlot(filled.contour(x1, x2, f, color.palette = bl2gr.colors))
  
  observeEvent(input$goButton, {
  
  output$plot3 <- renderPlot({
    GA <- ga(type = input$type_of, fitness =  function(x) - levy13(x[1], x[2]),
             lower = c(-10, -10), upper = c(10, 10), 
             popSize = input$pop, maxiter = input$epoch, run = 300)
    plot(GA)})
  })
}
1 Answers

Sure, we can make it so our Go button controls when the chart is redrawn. And stop the chart from redrawing when the sliders change.

We can use isolate to stop the chart being automatically linked to the sliders.

The below minimal example shows this in action:

library(shiny)

ui <- fluidPage(

    sliderInput("slider_1", "Slider 1", min = 1, max = 10, value = 5),
    sliderInput("slider_2", "Slider 2", min = 1, max = 10, value = 5),
    
    actionButton("myactionbutton", "Go"),
    
    plotOutput("myplot")
    
)

server <- function(input, output, session) {
  
    #Runs when action button is pressed
    observeEvent(input$myactionbutton, {
      
        #Prepare chart output
        output$myplot <- renderPlot({
            
            #Get the input of the sliders, but isolate them so changing the sliders won't cause our chart to redraw
            numberofpoints <- isolate(input$slider_1) * isolate(input$slider_2)
            
            #Prepare chart
            hist(runif(numberofpoints))
            
        })
        
    })
    
}

shinyApp(ui, server)

Here is your code with isolate added, wrapped in a few extra lines to make it a fully working shiny app:

library(shiny)
library(GA)
library(tidyverse)
library(ranger)
library(caret)
library(tictoc)

ui <- fluidPage(
    pageWithSidebar(
        headerPanel('Algorytm genetyczny - optymalizacja funkcji Levy13'),
        sidebarPanel(
            selectInput('type_of', 'Typ algorytmu', choices = c("real-valued", "binary"), multiple = FALSE),
            sliderInput('pop', 'Wielkosc populacji', min = 50, max = 1000, value = 100, step = 50, round = TRUE, animate = TRUE, width = '400px'),
            sliderInput('epoch', 'Liczba iteracji', min = 100, max = 2000, value = 1000, step = 100, round = TRUE, animate = TRUE, width = '400px'),
            actionButton("goButton", "Go!", class = "btn-success"),
        ),
        mainPanel(
            plotOutput('plot1'),
            plotOutput('plot2'),
            plotOutput('plot3')
        )
    )
)

server <- function(input, output, session) {
    
    levy13 <- function(x1, x2)
    {
        term1 <- (sin(3*pi*x1))^2
        term2 <- (x1-1)^2 * (1+(sin(3*pi*x2))^2)
        term3 <- (x2-1)^2 * (1+(sin(2*pi*x2))^2)
        
        y <- term1 + term2 + term3
        return(y)
    }
    
    x1 <- x2 <- seq(-10, 10, by = 0.1)
    f <- outer(x1, x2, levy13)
    
    output$plot1 <- renderPlot(persp3D(x1, x2, f, theta = 50, phi = 20, col.palette = bl2gr.colors) )
    
    output$plot2 <- renderPlot(filled.contour(x1, x2, f, color.palette = bl2gr.colors))
    
    observeEvent(input$goButton, {
        
        output$plot3 <- renderPlot({
            GA <- ga(type = input$type_of, fitness =  function(x) - levy13(x[1], x[2]),
                     lower = c(-10, -10), upper = c(10, 10), 
                     popSize = isolate(input$pop), maxiter = isolate(input$epoch), run = 300)
            plot(GA)})
        
    })
}

shinyApp(ui, server)
Related