How to run a calculation with a reactive action button in shiny

shiny
leaflet
rstudio

#1

I am trying to let shiny do a calculation with slide bar values after the user clicks on the action button. These slide bars represent five dimensions which the user can drag to set his preferred weight value per variable. After the action button has been clicked, the app should then show a map with municipalities that have the highest ‘score’ based on these weight values.

However, when I try to run the shiny app I get the error: “Error: invalid ‘type’ (list) of argument”

server.R:

library(shiny)

function(input, output, session) {

# Define new variable in SpatialPolygonsDataFrame to store calculated value 
    MunScores2016$Total_Score <- Total_Score
    Total_Score <- NA

# Use eventReactive() to delay reactions until user clicks the action button
    Total_Score <- eventReactive(input$action, {
    ((input$housingslider * MunScores2016$Housing_Score_2016 +
    input$populationslider * MunScores2016$Population_Score_2016 +
    input$provisionsslider * MunScores2016$Provisions_Score_2016 +
    input$safetyslider * MunScores2016$Safety_Score_2016 +
    input$physicalenvslider * MunScores2016$PhysicalEnvironment_Score_2016)/
    (input$housingslider + input$populationslider + input$provisionsslider + input$safetyslider + input$physicalenvslider))})


 output$mymap <- renderLeaflet({
 #Create new color palette
     pal2 <- colorNumeric(
     palette = "Greens",
     domain = Total_Score,
     n = 6)
 #Create interactive map
    leaflet(data = MunScores2016) %>% addTiles() %>%
      addPolygons(fillColor = ~pal2(Total_Score), 
                  fillOpacity = 1, 
                  color = 'white', 
                  weight = 1,
                  popup = paste0("<strong>Municipality: </strong>", 
                             MunScores2016$Municipality_Name, 
                             "<br><strong>Quality-of-life-o-meter says: </strong>", 
                             Total_Score)) %>%
      addLegend("bottomright", # Legend position
                pal=pal2, # color palette
                values=~Total_Score, # legend values
                opacity = 0.7,
                title="Percentage difference from national average")
  })

}

#2

Without any insight into your ui or data structure, its difficult to give an exact answer. That being said, you need to mutate the data.frame you’re using with the values from the input sliders, such that eventReactive produces a new dataframe with a totalScore variable that you use in the leaflet() function. Example:

totalScoreDf <- eventReactive(input$action, {
MunScores2016 %>%
mutate(
totalScore = ((input$housingslider * MunScores2016$Housing_Score_2016 +
    input$populationslider * MunScores2016$Population_Score_2016 +
    input$provisionsslider * MunScores2016$Provisions_Score_2016 +
    input$safetyslider * MunScores2016$Safety_Score_2016 +
    input$physicalenvslider * MunScores2016$PhysicalEnvironment_Score_2016)/
    (input$housingslider + input$populationslider + input$provisionsslider + input$safetyslider + input$physicalenvslider))
)

leaflet(data = totalScoreDf) %>% addTiles() %>%
      addPolygons(fillColor = ~pal2(Total_Score), 
                  fillOpacity = 1, 
                  color = 'white', 
                  weight = 1,
                  popup = paste0("<strong>Municipality: </strong>", 
                             MunScores2016$Municipality_Name, 
                             "<br><strong>Quality-of-life-o-meter says: </strong>", 
                             Total_Score)) %>%
      addLegend("bottomright", # Legend position
                pal=pal2, # color palette
                values=~totalScore, # legend values
                opacity = 0.7,
                title="Percentage difference from national average")

#3

Hi soedr, thanks a lot for your reply! I’ll have a look at your solution. In the meantime I got another suggestion of someone else which also seems to work fine:

server <- function(input, output, session) {
  
  # Create Map once.
  output$mymap <-renderLeaflet({
    leaflet(data = MunScores2016) %>%
    addTiles() %>%
    addPolygons(
      fillColor = ~pal(Total_Score_2016),
      fillOpacity = 1, 
      color = 'white', 
      weight = 1,
      popup = popup_dat) %>%
    addLegend(
      "bottomright",
      pal=pal,
      values=~Total_Score_2016,
      opacity = 0.7,
      title="Percentage difference from national average") 
  })
  
  observeEvent(input$action, {
    Total_Score <- NA
    Total_Score <- ((input$housingslider * MunScores2016$Housing_Score_2016 +
                       input$populationslider * MunScores2016$Population_Score_2016 +
                       input$provisionsslider * MunScores2016$Provisions_Score_2016 +
                       input$safetyslider * MunScores2016$Safety_Score_2016 +
                       input$physicalenvslider * MunScores2016$PhysicalEnvironment_Score_2016)/
                      (input$housingslider + input$populationslider + input$provisionsslider + input$safetyslider + input$physicalenvslider))
    
    # Just update the existing map
    leafletProxy("mymap") %>% 
    # This you have to do now: remove the existing polygons, before you paint new ones.
    clearShapes() %>% 
    addPolygons(
      data = MunScores2016,
      fillColor = ~pal(Total_Score), 
      fillOpacity = 1, 
      color = 'white', 
      weight = 1,
      popup = paste0("<strong>Municipality:</strong>", 
                     MunScores2016$Municipality_Name, 
                     "<br><strong>Quality-of-life-o-meter says: </strong>", 
                     Total_Score))
    # As you can see, no addLegend is needed, since the legend does not change. 
  })