Search code examples
rshinyr-leaflet

Filter map using Leaflet and Shiny in R - multiple value attributes


I am trying to filter points on a map based on attributes. It works fine as long as one attribute contains only one value. In case that one attribute has multiple values (i.e. "water;sand") I am not able to map this point based on the filter.

Here is my minimum example:

library(data.table)
mydat <- data.table( londd=c(20, 38, 96, 32),
                     latdd=c(60, 56, 30, 31),
                     art=c("mountain", "water,sand", "sand", "forest"),
                     anwendung=c("a","b","c","d"))

#Set up ui
ui <- shinyUI(fluidPage(
sidebarPanel(h5("", width=2),
     checkboxGroupInput(inputId="ArtFlag", label=h4("Art des Bodens"), 
        choices=setNames(object=c("mountain", "water", "sand", "forest"),
                           nm=c("mountain", "water", "sand", "forest"))),
     checkboxGroupInput(inputId="AnwendungFlag", label=h4("Anwendung"), 
        choices=setNames(object=c("a","b","c","d"),
                           nm=c("a","b","c","d"))),
position="left"),
#App mainPanel content and styles
mainPanel(fluidRow(leafletOutput(outputId="lmap")))
              )
            )
          )

#Set up server
server <- function(input, output){
#Build leaflet map
lmap <- leaflet(data=mydat)%>%
addProviderTiles("Stamen.TonerLite", options = providerTileOptions(noWrap = TRUE)) %>%
fitBounds(~min(londd), ~min(latdd), ~max(londd), ~max(latdd))

#Filter data
datFilt <- reactive(mydat[art%in%input$ArtFlag & anwendung%in%input$AnwendungFlag])

#Add markers based on selected flags
observe({
  if(nrow(datFilt())==0) {print("Nothing selected");leafletProxy("lmap") %>% clearShapes()}
    else{ #print(paste0("Selected: ", unique(input$InFlags & input$InFlags2)))
  
    leafletProxy("lmap", data=datFilt())%>%clearShapes()%>%
    addCircleMarkers(lng=~londd, lat=~latdd,
                     clusterOptions=markerClusterOptions(), weight=3,
                     color="#33CC33", opacity=1, fillColor="#FF9900", 
                     fillOpacity=0.8)%>% clearShapes()
        }
     })

   output$lmap <- renderLeaflet(lmap)
}

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

Solution

  • Well, I'm not 100% sure this solves what you're looking for, so please leave a comment if it doesn't. Your problem is in your reactive statement - you don't have a checkbox for "water,sand", so you'll never get a match for checkbox B. To get a match for checkbox B regardless of if water or sand was selected, I tried this, using grepl to get a pattern match, rather than an exact match. Try changing your datFilt call to this:

      #Filter data
      datFilt <- reactive({
    
        filterName <- ifelse(length(input$ArtFlag) == 0, 'none', input$ArtFlag)
    
        mydat[grepl(filterName, art) & anwendung%in%input$AnwendungFlag]
        })
    

    (This is probably not the most efficient code to do this, but hopefully it will either work or get you closer to what you're looking for. In a perfect world, it might be easier to code for this if the structure of your data was different, but not sure if that's an option for you or not)