Search code examples
rshinyr-leaflet

Shiny leaflet map - filtering data by columns, not rows


First, I have a perfect solution here how to create a Shiny leaflet map and filters based on rows.

Now I want to show a very similar map, where filters are applied to columns. Stumbled a little bit.

I want to create a map of US adult smoking by year, highlighting % with different colors.

Data in .csv format is here

Shapefiles are here

Currently, my map looks like this

Currently, my map looks like this

This is my code:

# Set directory
setwd("C:/DC/R/Shiny/US Adult Smoking by State")

# Upload packages
library(ggthemes)
library(rgdal)
library(sp)
library(leaflet)
library(shinythemes)

# Read dataset
smoking <- read.csv("US adult smoking by state1.csv", header = TRUE)

# Leaflet map
states <- readOGR(dsn = "C:/DC/R/Cool datasets/US smoking", layer = 
"cb_2016_us_state_500k", 
              encoding = "UTF-8", verbose = FALSE)

# Merge data
# require(sp)! For spatial dataframe!
smoking.df <- merge(states, smoking, by.x = "NAME", by.y = "state")
class(smoking.df)

# Create palette
pal <- colorBin("Reds", c(0, 30), na.color = "#808080",
            alpha = FALSE, reverse = FALSE)


# UI
ui <- shinyUI(fluidPage(theme = shinytheme("united"),
                    titlePanel(HTML("<h1><center><font size=14> US Adult 
Smoking by State in 2015-2017</font></center></h1>")), 
                    sidebarLayout(
                      sidebarPanel(
                        selectInput("stateInput", label = h3("State"),
                                    choices = c("Choose state",
                                                "Alabama",
                                                "Alaska",
                                                "Arizona",
                                                "Arkansas",
                                                "California",
                                                "Colorado",
                                                "Connecticut",
                                                "Delaware",
                                                "Florida",
                                                "Georgia",
                                                "Hawaii",
                                                "Idaho",
                                                "Illinois",
                                                "Indiana",
                                                "Iowa",
                                                "Kansas",
                                                "Kentucky",
                                                "Louisiana",
                                                "Maine",
                                                "Maryland",
                                                "Massachusetts",
                                                "Michigan",
                                                "Minnesota",
                                                "Mississippi",
                                                "Missouri",
                                                "Montana",
                                                "Nebraska",
                                                "Nevada",
                                                "New Hampshire",
                                                "New Jersey",
                                                "New Mexico",
                                                "New York",
                                                "North Carolina",
                                                "North Dakota",
                                                "Ohio",
                                                "Oklahoma",
                                                "Oregon",
                                                "Pennsylvania",
                                                "Rhode Island",
                                                "South Carolina",
                                                "South Dakota",
                                                "Tennessee",
                                                "Texas",
                                                "Utah",
                                                "Vermont",
                                                "Virginia",
                                                "Washington",
                                                "West Virginia",
                                                "Wisconsin",
                                                "Wyoming"
                                                ),
                                    selected = "Choose state"),
                        selectInput("stateInput", label = h3("State"),
                                    choices = c("Choose year",
                                                "2015",
                                                "2016",
                                                "2017"),
                                    selected = "Choose year")),
                      mainPanel(leafletOutput(outputId = 'map', height = 
800) 
                          ))
                    ))



# SERVER
server <- shinyServer(function(input, output) {
output$map <- renderLeaflet({
leaflet(smoking.df) %>% 
  addProviderTiles(providers$Stamen.TonerLite) %>% 
  setView(lng = -98.583, lat = 39.833, zoom = 4) #%>% 

})
# observers

# selected state
selectedState <- reactive({
smoking.df[smoking.df$NAME == input$stateInput, ] 
})

observe({
state_popup <- paste0("<strong>State: </strong>", 
                      selectedState()$NAME, 
                      "<br><strong>% of smoking adults in 2015: </strong>",
                      selectedState()$adult_smoking_2015,
                      "<br><strong>% of smoking adults in 2016: </strong>",
                      selectedState()$adult_smoking_2016,
                      "<br><strong>% of smoking adults in 2017: </strong>",
                      selectedState()$adult_smoking_2017)

leafletProxy("map", data = selectedState()) %>%
  clearShapes() %>%
  addPolygons(fillColor = "orange",
              popup = state_popup,
              color = "#BDBDC3",
              fillOpacity = 0.8,
              weight = 1)
})

# selected year
selectedYear <- reactive({
smoking.df[smoking.df$adult_smoking_2015 == input$yearInput &
           smoking.df$adult_smoking_2016 == input$yearInput &
           smoking.df$adult_smoking_2017 == input$yearInput,] 
})

observe({
state_popup1 <- paste0("<strong>State: </strong>", 
                      selectedState()$NAME)

leafletProxy("map", data = selectedYear()) %>%
  clearShapes() %>%
  addPolygons(fillColor = ~pal(selectedYear()$yearInput),
              popup = state_popup1,
              color = "#BDBDC3",
              fillOpacity = 0.8,
              weight = 1)
})


})


# Run app! 
shinyApp(ui = ui, server = server)

So, my assumption that I am screwing up with inputYear, and also with the color palette in leaflet map. Years are in columns and it is a little bit difficult for me now to understand where is my mistake.

My desirable outcome, which I created just in leaflet below. I want to change year in a filter and receive the change on a map. enter image description here


Solution

  • Preliminary solution (not mine, from other smart people). Plus the shapefile was substituted with geojson one.

    # Upload packages
    library(rgdal)
    library(sp)
    library(leaflet)
    library(geojsonio)
    library(shinythemes)
    library(shiny)
    
    # Read dataset
    smoking <- read.csv("US adult smoking by state1.csv", header = TRUE)
    
    # Leaflet map
    # states <- readOGR(dsn = ".", layer = 
    #                    "cb_2016_us_state_500k", 
    #                   encoding = "UTF-8", verbose = FALSE)
    
    states <- geojson_read("gz_2010_us_040_00_500k.json",what = "sp")
    
    # Merge data
    # require(sp)! For spatial dataframe!
    smoking.df <- merge(states, smoking, by.x = "NAME", by.y = "state")
    
    
    # UI
    ui <- shinyUI(fluidPage(theme = shinytheme("united"),
                        titlePanel(HTML("<h1><center><font size=14> US Adult 
                                        Smoking by State in 2015-2017</font>
    </center></h1>")), 
                        sidebarLayout(
                          sidebarPanel(
                            selectizeInput(
                              "stateInput", 'State', choices = "", multiple = 
    FALSE,
                              options = list(
                                placeholder = 'Please select a state from 
    below')
                            )
                            ,
                            selectInput("yearInput", label = h3("Year"),
                                        choices = c("Choose year", "2015", # 
     Choose year was added!
                                                    "2016",
                                                    "2017"))),
                          mainPanel(leafletOutput(outputId = 'map', height = 
                                                    800) 
                          ))
                        ))
    
    
    # SERVER
    server <- shinyServer(function(input, output, session) {
    
    updateSelectizeInput(session, "stateInput", choices = smoking.df$NAME,
                       server = TRUE)
    # selected state
    selectedState <- reactive({
    smoking.df[smoking.df$NAME == input$stateInput, ] 
    })
    # selected year
    selectedYear <- reactive({switch(input$yearInput, 
                                   "2015"=smoking.df$adult_smoking_2015, 
                                   "2016"=smoking.df$adult_smoking_2016, 
                                   "2017"=smoking.df$adult_smoking_2017)
    })
    pal2 <- colorNumeric(palette = "Reds", domain=NULL)
    
    output$map <- renderLeaflet({
    leaflet(smoking.df) %>% 
      addProviderTiles(providers$Stamen.TonerLite) %>% 
      setView(lng = -98.583, lat = 39.833, zoom = 4) %>%
      addPolygons(data = smoking.df ,fillColor = ~pal2(selectedYear()),
                  popup = paste0("<strong>State: </strong>", 
                                 smoking.df$NAME),
                  color = "#BDBDC3",
                  fillOpacity = 0.8,
                  weight = 1)
    
      })
    
      observeEvent(input$stateInput, {
      state_popup <- paste0("<strong>State: </strong>", 
                          selectedState()$NAME, 
                          "<br><strong>% of smoking adults in 2015: </strong>",
                          selectedState()$adult_smoking_2015,
                          "<br><strong>% of smoking adults in 2016: </strong>",
                          selectedState()$adult_smoking_2016,
                          "<br><strong>% of smoking adults in 2017: </strong>",
                          selectedState()$adult_smoking_2017)
    
        leafletProxy("map", data = selectedState()) %>%
      clearGroup(c("st.ate")) %>%
      addPolygons(group ="st.ate",fillColor = "orange",
                  popup = state_popup,
                  color = "#BDBDC3",
                  fillOpacity = 0.8,
                  weight = 5)
    })
    
    })
    
    # Run app! 
    shinyApp(ui = ui, server = server)
    

    Current outputs: Just a map by year

    A map by year with selected state

    Current problems:

    1. Map is still slow with geojson, 2 seconds for changing years, it is redrawing.

    2. Gray color is on a map without any picks. Any ideas? As for now

    Will keep you posted, will try to add one more filter.