rshinyr-sfr-leaflet

Shiny Leaflet not being able to pick user uploaded shapefile(sf_object) data path


I am creating a shiny app that:

  1. Allows the user to upload a shapefile (sf_object) "filemap" (I am assuming sf wants all the files associated with a shapefile exported from ArcPro).
  2. Based on the uploaded shapefile, the user will then be able to select a column/variable of interest to map (mapview).

I am getting this error while the app is loaded:

Error in pointData.default: Don't know how to get path data from object of class character

How can I fix this error?

Sample data (part of the data from the shapefile to be uploaded):

structure(list(Info = c(NA_character_, NA_character_, NA_character_, 
NA_character_, NA_character_), tmean = c(22.2395992279053, 22.7657985687256, 
24.4260005950928, 19.601001739502, 17.5659999847412), CITYNAME = c("NORTH LAUDERDALE", 
"NORTH LAUDERDALE", "NORTH LAUDERDALE", "NORTH LAUDERDALE", "NORTH LAUDERDALE"
), Model = c("PRISM", "PRISM", "PRISM", "PRISM", "PRISM"), Variable = c("tmean", 
"tmean", "tmean", "tmean", "tmean"), Datatype = c("provisional", 
"provisional", "stable", "stable", "stable"), Resolution = c("4kmM3", 
"4kmM3", "4kmM3", "4kmM3", "4kmM3"), year = c(2021L, 2021L, 1980L, 
1980L, 1980L), month = c(11L, 12L, 0L, 1L, 2L), TMin = c(0, 0, 
0, 0, 0), TMax = c(0, 0, 0, 0, 0), geometry = structure(list(
    structure(c(-80.2083333327448, 26.2083333333333), class = c("XY", 
    "POINT", "sfg")), structure(c(-80.2083333327448, 26.2083333333333
    ), class = c("XY", "POINT", "sfg")), structure(c(-80.2083333327448, 
    26.2083333333333), class = c("XY", "POINT", "sfg")), structure(c(-80.2083333327448, 
    26.2083333333333), class = c("XY", "POINT", "sfg")), structure(c(-80.2083333327448, 
    26.2083333333333), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT", 
"sfc"), precision = 0, bbox = structure(c(xmin = -80.2083333327448, 
ymin = 26.2083333333333, xmax = -80.2083333327448, ymax = 26.2083333333333
), class = "bbox"), crs = structure(list(input = "WGS 84", wkt = "GEOGCRS[\"WGS 84\",\n    DATUM[\"World Geodetic System 1984\",\n        ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n            LENGTHUNIT[\"metre\",1]]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"latitude\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"longitude\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    ID[\"EPSG\",4326]]"), class = "crs"), n_empty = 0L)), row.names = c(NA, 
-5L), class = c("sf", "data.frame"), sf_column = "geometry", agr = structure(c(Info = NA_integer_, 
tmean = NA_integer_, CITYNAME = NA_integer_, Model = NA_integer_, 
Variable = NA_integer_, Datatype = NA_integer_, Resolution = NA_integer_, 
year = NA_integer_, month = NA_integer_, TMin = NA_integer_, 
TMax = NA_integer_), class = "factor", .Label = c("constant", 
"aggregate", "identity")))

UI

library(shiny)
library(shinydashboard)
library(shinythemes)
library(tidyverse)
library(RColorBrewer)
library(png)
library(shinyWidgets)
library(sf)
library(leaflet)


    # Define UI for application that draws an interactive ggplot
    options(shiny.maxRequestSize=30*1024^2)
    ui =   navbarPage("Temperature Analysis", theme = shinytheme("sandstone"),
                    tabPanel("Temperature",
                    icon = icon("chart-area"),
                    sidebarLayout(sidebarPanel(fileInput("filemap", label = "Input Shapefile 
                                                         (.shp,.dbf,.sbn,.sbx,.shx,.prj)",
                                                         multiple=TRUE,
                                                         accept = c(".shp",
                                                                    ".dbf",
                                                                    ".sbn",
                                                                    ".sbx",
                                                                    ".shx",
                                                                    ".prj",
                                                                    ".cpg",
                                                                    ".xml"))),
                    mainPanel(selectInput(inputId = "Temp", label = "Select Temperature Variable", choices = c("Mean Temperature" = "TMean", "Minimum Temperature" = "TMin", "Maximum Temperature" = "TMax")),
                              leafletOutput("mapview")))))

Server

# Tell the server how to assemble inputs into outputs
    server = function(input, output, session) {
            
            # Read-in shapefile function
        Read_Shapefile = function(shp_path) {
          infiles = shp_path$datapath # get the location of files
          dir = unique(dirname(infiles)) # get the directory
          outfiles = file.path(dir, shp_path$name) # create new path name
          name = strsplit(shp_path$name[1], "\\.")[[1]][1] # strip name 
          purrr::walk2(infiles, outfiles, ~file.rename(.x, .y)) # rename files
          x = read_sf(file.path(dir, paste0(name, ".shp"))) # read-in shapefile
          return(x)
        }
        
        # Read-shapefile once user submits files
        
          observe({
            req(input$filemap)
            Temp_map =  Read_Shapefile(input$filemap)
                
           pal_fun = colorQuantile("YlOrRd", NULL, n = 5) # Define color palette and classes
          
          t_popup = paste0("Air Temperature", input$Temp) # Popup depends on the "Temp" variable selected 
          
          output$mapview =  renderLeaflet({leaflet(input$Temp) %>% # Map depends on the "Temp" variable selected
          addCircleMarkers(
          fillColor = ~pal_fun(input$Temp), # set fill color with function from above and value
          fillOpacity = 0.8, # make it nicer
          popup = t_popup)
          })
          
          })
        
        
    
}   

Upon selecting a variable to map, I get further warnings/errors:

enter image description here

Warning in file.rename(.x, .y) :
  cannot rename file 'C:\Users\ed\AppData\Local\Temp\RtmpWWEmJR/48579773928f2819571ef8e5/0.cpg' to 'C:/Users/ed/AppData/Local/Temp/RtmpWWEmJR/48579773928f2819571ef8e5/BCU_Temp_1980_2021.cpg', reason 'The system cannot find the file specified'
Warning in file.rename(.x, .y) :
  cannot rename file 'C:\Users\ed\AppData\Local\Temp\RtmpWWEmJR/48579773928f2819571ef8e5/1.dbf' to 'C:/Users/ed/AppData/Local/Temp/RtmpWWEmJR/48579773928f2819571ef8e5/BCU_Temp_1980_2021.dbf', reason 'The system cannot find the file specified'
Warning in file.rename(.x, .y) :
  cannot rename file 'C:\Users\ed\AppData\Local\Temp\RtmpWWEmJR/48579773928f2819571ef8e5/2.prj' to 'C:/Users/ed/AppData/Local/Temp/RtmpWWEmJR/48579773928f2819571ef8e5/BCU_Temp_1980_2021.prj', reason 'The system cannot find the file specified'
Warning in file.rename(.x, .y) :
  cannot rename file 'C:\Users\ed\AppData\Local\Temp\RtmpWWEmJR/48579773928f2819571ef8e5/3.sbn' to 'C:/Users/ed/AppData/Local/Temp/RtmpWWEmJR/48579773928f2819571ef8e5/BCU_Temp_1980_2021.sbn', reason 'The system cannot find the file specified'
Warning in file.rename(.x, .y) :
  cannot rename file 'C:\Users\ed\AppData\Local\Temp\RtmpWWEmJR/48579773928f2819571ef8e5/4.sbx' to 'C:/Users/ed/AppData/Local/Temp/RtmpWWEmJR/48579773928f2819571ef8e5/BCU_Temp_1980_2021.sbx', reason 'The system cannot find the file specified'
Warning in file.rename(.x, .y) :
  cannot rename file 'C:\Users\ed\AppData\Local\Temp\RtmpWWEmJR/48579773928f2819571ef8e5/5.shp' to 'C:/Users/ed/AppData/Local/Temp/RtmpWWEmJR/48579773928f2819571ef8e5/BCU_Temp_1980_2021.shp', reason 'The system cannot find the file specified'
Warning in file.rename(.x, .y) :
  cannot rename file 'C:\Users\ed\AppData\Local\Temp\RtmpWWEmJR/48579773928f2819571ef8e5/6.xml' to 'C:/Users/ed/AppData/Local/Temp/RtmpWWEmJR/48579773928f2819571ef8e5/BCU_Temp_1980_2021.shp.xml', reason 'The system cannot find the file specified'
Warning in file.rename(.x, .y) :
  cannot rename file 'C:\Users\ed\AppData\Local\Temp\RtmpWWEmJR/48579773928f2819571ef8e5/7.shx' to 'C:/Users/ed/AppData/Local/Temp/RtmpWWEmJR/48579773928f2819571ef8e5/BCU_Temp_1980_2021.shx', reason 'The system cannot find the file specified'
Warning: Error in pointData.default: Don't know how to get location data from object of class character

UPDATE 1

I tried changing the code a bit and now the error is gone but I am not getting the leaflet output.

enter image description here

Posting only the changed code:

# Read-shapefile once user submits files
Temp_map =   reactive({
        req(input$filemap)
         Read_Shapefile(input$filemap)
      
      pal_fun = colorQuantile("YlOrRd", NULL, n = 5) # Define color palette and classes
      
      observe({
        data = Temp_map
        updateSearchInput(session, "Temp", choices = names(data))
      })
      
      t_popup = paste0("Air Temperature", input$Temp) # Popup depends on the "Temp" variable selected 
      
      output$mapview =  renderLeaflet({leaflet(input$Temp) %>% # Map depends on the "Temp" variable selected
        addCircleMarkers(data = input$Temp,
          fillColor = ~pal_fun(input$Temp), # set fill color with function from above and value
          fillOpacity = 0.8, # make it nicer
          popup = t_popup)  # add popup
      })
      
      })

UPDATE 2

I have further modified the code. Now the select input menu is able to pick up the columns from the shapefile. However, leaflet is still returning the same error.

Error in pointData.default: Don't know how to get path data from object of class character

Part of code that I changed:

# Read-shapefile once user submits files
        
        Temp_map =   reactive({
            req(input$filemap)
          df = Read_Shapefile(input$filemap)
          df
        })
          # # Code for allowing the user to select the variables/columns of interest to map
          # info = eventReactive(input$Temp, {
          #   req(Temp_map())
          #   t = Temp_map()
          #   t
          # })
         
          # observe({
          #   req(input$Temp) 
          #   updateSelectInput(session,"Temp", "Please select the temperature variable to map:", choices = names(Temp_map))
          # }) # Allows the user to select the column/variable to map based on uploaded shapefile (Temp_map)
          
          pal_fun = colorQuantile("YlOrRd", NULL, n = 5) # Define color palette and classes
          
          observe({
            dff = Temp_map()
            updateSelectInput(session, "Temp", choices = names(dff))
          })
          
          #t_popup = paste0("Air Temperature", input$Temp) # Popup depends on the "Temp" variable selected 
          
          output$mapview =  renderLeaflet({leaflet() %>% # Map depends on the "Temp" variable selected
            addCircleMarkers(data = input$Temp,
              fillColor = ~pal_fun(input$Temp), # set fill color with function from above and value
              fillOpacity = 0.8, # make it nicer
              popup = TRUE)  # add popup
          })

enter image description here


Solution

  • Shouldn't you be supplying Temp_map() as your data for leaflet or mapview to produce the map and then supply input$temp as the variable for your colours?