Search code examples
rshinyshinydashboard

Updating chloropleth map based on radio button input


I am creating a shiny dashboard to visualize the spread of COOVID 19 across the states of Australia.

The following is my data frame (covid_cases) with the number of confirmed cases, deaths and recoveries

  region                       Confirmed Deaths Recovered
  <chr>                            <dbl>  <dbl>     <dbl>
1 Australian Capital Territory       113      3       110
2 New South Wales                   4218     53      3118
3 Northern Territory                  33      0        31
4 Queensland                        1157      6      1141
5 South Australia                    468      4       462
6 Tasmania                           230     13       217
7 Victoria                         20149    787     18901
8 Western Australia                  676      9       651
 

In my server, I join the covid_cases data frame with the shapefile and color the states using the 'Cofirmed' cases. This works fine.

server <- function(input, output) {
  
  output$ausmap <- renderLeaflet({
    states_data <-  read_sf("https://raw.githubusercontent.com/rowanhogan/australian-states/master/states.geojson") %>%
      dplyr::left_join(covid_cases, by=c("STATE_NAME" = "region"))
    pal <- colorQuantile("Blues", domain = states_data$Confirmed)
    leaflet(states_data) %>%
      addTiles() %>%
      addPolygons(fillColor=~pal(Confirmed),
                  fillOpacity=0.8,
                  color="white", weight=1) %>%
      fitBounds(110.246193, -50.322817, 155.226126, -9.088012)
    
  })

}

However, I now want to color the states based on user input. And Have implemented the following radioGroupButtons in my UI component.

UI <- dashboradBody(
fluidRow(
                radioGroupButtons(
                  inputId = "casetype",
                  label = NULL,
                  choices = c("Confirmed", "Deaths", "Recovered"),
                  selected = "Confirmed"
                ),
                leafletOutput("ausmap")
                )
)

and updated my server as follows

  server <- function(input, output) {
      
  output$ausmap <- renderLeaflet({
    states_data <-  read_sf("https://raw.githubusercontent.com/rowanhogan/australian-states/master/states.geojson") %>%
      dplyr::left_join(covid_cases, by=c("STATE_NAME" = "region"))
    pal <- colorQuantile("Blues", domain = states_data$Confirmed)
    leaflet(states_data) %>%
      addTiles() %>%
      addPolygons(fillColor=~pal(input$casetype),
                  fillOpacity=0.8,
                  color="white", weight=1) %>%
      fitBounds(110.246193, -50.322817, 155.226126, -9.088012)
    
  })

}

This gives me an error stating "'x' must be numeric".

I would also like to change the color palette based on the input (ex: deaths - red, confirmed -blue, recovered - green). But am unsure how to update this.


Solution

  • I am not sure, if it's the best way (somehow it feels like this should be done with reactive values, but I am still trying to figure out the details of shiny ... especially the reactive details :D) ... anyways ... here is a solution that should work :)

    The trick was to use helper variables for the casetype and pal. The error you got (numeric input) was, because pal needs the numeric data (deaths,...) to map the color and not the category (casetype)

    output$ausmap <- leaflet::renderLeaflet({
        url <- paste0("https://raw.githubusercontent.com/rowanhogan/",
                     "australian-states/master/states.geojson")
    
        selected_col <- switch(input$casetype,
                               "Confirmed"="Blues",
                               "Deaths"="Reds",
                               "Recovered"="Greens")
    
        states_data <-  sf::read_sf(url) %>%
          dplyr::left_join(covid_cases %>%
                             dplyr::select(region,selected=input$casetype),
                           by=c("STATE_NAME" = "region"))
        pal <- leaflet::colorQuantile(selected_col, domain = states_data$selected)
        leaflet::leaflet(states_data) %>%
          leaflet::addTiles() %>%
          leaflet::addPolygons(fillColor=~pal(selected),
                               fillOpacity=0.8,
                               color="white",
                               weight=1) %>%
          leaflet::fitBounds(110.246193, -50.322817, 155.226126, -9.088012)
    
      })