Sandeep Patil
Sandeep Patil

Reputation: 47

Plot empty maps with lat long data missing Shiny

I have a Shiny app that shows leaflet map on load Image 1. I have added reactivity to plot lat long data once users upload some data with lat long information. It works fine if the upload data has lat long info like in df1 below. It adds makers based on latitude & longitude columns. Till here it is fine & good Image 2. enter image description here

df1 <- data.frame(Category = c("Dining", "Master", "Breakfast", "Hidden"), 
                      latitude = c(28.7041, 19.0760, 12.9716, 17.3850), 
                      longitude = c(77.1025, 72.8777, 77.5946, 78.4867))

enter image description here

The app crashes if latitude longitude info is missing in the upload file like in df2 below with warning. The upload file will have latitude & longitude columns but will not have any data.

df2 <- data.frame(Category = c("Dining", "Master", "Breakfast", "Hidden"), 
                  latitude = c("","","",""), 
                  longitude = c("","","",""))

Warning: Error in validateCoords: addCircleMarkers requires numeric longitude/latitude values

The need or requirement here are as below.

  1. If the upload file is missing latitude & longitude values but not the columns as such, leaflet map should be without any markers like Image 1. It should just by pass plotting markers.
  2. If possible, show a warning message that app could not be plot map because of missing latitude & longitude info. Close the warning message & carry forward.

Any help is much appreciated.

This is my reprex.

library(shiny)
library(shinydashboard)
library(leaflet)
library(tidyverse)
library(DT)

ui <- dashboardPage(
  dashboardHeader(title = "Map Data"),
  dashboardSidebar(
    fileInput("file1", "Upload Data file", accept = ".csv")),
  dashboardBody(
    DT::dataTableOutput("table1"),
    leafletOutput("map1"))
)

server <- function(input, output, session) {
  data <- reactive({
    df <- input$file1
    if(is.null(df))
      return(NULL)
    df <- read.csv(df$datapath, header = TRUE, sep = ",", row.names = NULL)
    return(df)
  })
  
  output$table1 <- renderDataTable(data())
  
  mapdata <- eventReactive({
    data()
  } ,  {
     req(data)
     if(is.null(input$select) || input$select == "")
      data() else
         data
   })
   
  observe({
    leafletProxy("map1", data = mapdata()) %>%
      clearShapes() %>%
      addCircleMarkers(lng = mapdata()$longitude, lat = mapdata()$latitude, radius = 8, weight = 1, color = "blue", fillOpacity = 0.5, label = mapdata()$Subsite,
                       labelOptions = labelOptions(noHide = F, textsize = "15px"))
  })
  
  output$map1 <- renderLeaflet({
    leaflet() %>%
      addProviderTiles(providers$Esri.WorldImagery) %>%
      addProviderTiles(providers$Stamen.TonerHybrid) %>%
      setView(100.46, 23, 4)
  })
  }

shinyApp(ui, server)

Upvotes: 0

Views: 81

Answers (1)

YBS
YBS

Reputation: 21349

You need to check for missing values. Change your observer as shown below

  observe({

    if (!is.null(data())) {
      dfc <- data()[!is.na(data()$longitude) & data()$longitude !="" & 
                      !is.na(data()$latitude) & data()$latitude !="",]
      
      if (nrow(dfc)==0) {
        
        dfc$latitude <- as.numeric(dfc$latitude)
        dfc$longitude <- as.numeric(dfc$longitude)
        
        leafletProxy("map1", data=dfc) %>%
          clearMarkers() 
        
        ### display warning
        showModal(modalDialog(
          title = "WARNING: No latitude or longitude value present in the dataset uploaded",
          size = "s",
          easyClose = TRUE 
        ))
      }else {
        
        leafletProxy("map1", data = mapdata()) %>%
          clearShapes() %>%
          addCircleMarkers(lng = mapdata()$longitude, lat = mapdata()$latitude, radius = 8, weight = 1, color = "blue", fillOpacity = 0.5, label = mapdata()$Subsite,
                           labelOptions = labelOptions(noHide = F, textsize = "15px"))
      }
    }
  })

Upvotes: 2

Related Questions