rshinyr-sfr-leaflet

Object Temp_Map not found while trying to render a Leaflet Map


I know this question has been asked a lot of time, but every question varies according to the code/purpose. That being said I am creating shiny app that:

  1. Allows the user to upload a shapefile (sf_object) "filemap".
  2. Based on the uploaded shapefile, the user will then be able to select a column/variable of interest to map (mapview).
  3. The user will be also be able choose three variables from the same shapefile as x and y axis arguments for some plotly timeseries plot. But for now this is not part of the question.

I am getting this error while running the app:

Error in input$Temp : Can't access reactive value 'Temp' outside of reactive consumer. i Do you need to wrap inside reactive() or observe()? Warning: Error in updateSelectInput: object 'Temp_map' not found

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("Introduction",
                icon = icon("info"),
                img(src="tenor (1).gif", align = "topleft",height='90px',width='90px'),
                div(p(h1("Objective"),style="text-align: justify;", "The app focuses on analyzing air temperature trends over a 40 year period. The purpose was to see how much the climate has changed over time. Second objective of this project was to make a Shiny app that serves three purposes for the user:")),
                p("1. The user can upload a shapefile and the app will return a Chloropleth map."),
                p("2. Based on the uploaded shapefile, the app will return a interactive timeseries plot."),
                p("3. Based on the uploaded shapefile, the app will return the regression results and an interactive resultant regression plot."),
                uiOutput("all")),
                tabPanel("Temperature Timeseries Plot",
                icon = icon("chart-area"),
                img(src="tenor (2).gif", align = "topleft",height='90px',width='90px'),
                sidebarLayout(sidebarPanel(fileInput("filemap", label = "Input Shapefile 
                                                     (.shp,.dbf,.sbn,.sbx,.shx,.prj)",
                                                     multiple=TRUE,
                                                     accept = c(".shp",
                                                                ".dbf",
                                                                ".sbn",
                                                                ".sbx",
                                                                ".shx",
                                                                ".prj"))),
                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)})
          
          # 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
          # })

       
          observeEvent(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
          
          t_popup = paste0("Air Temperature", input$Temp) # Popup depends on the "Temp" variable selected 
          
          output$mapview =  renderLeaflet({(input$Temp) %>% # Map depends on the "Temp" variable selected
            addPolygons(
              stroke = FALSE, # remove polygon borders
              fillColor = ~pal_fun(input$Temp), # set fill color with function from above and value
              fillOpacity = 0.8, smoothFactor = 0.5, # make it nicer
              popup = t_popup)  # add popup
          })
}

Solution

  • The problem was caused by having two observe functions. Removing the second one removes the error.

    Server

     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)
              
              # # Code for allowing the user to select the variables/columns of interest to map
              
              # 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
              
              t_popup = paste0("Air Temperature", input$Temp) # Popup depends on the "Temp" variable selected 
              
              output$mapview =  renderLeaflet({(input$Temp) %>% # Map depends on the "Temp" variable selected
                addPolygons(
                  stroke = FALSE, # remove polygon borders
                  fillColor = ~pal_fun(input$Temp), # set fill color with function from above and value
                  fillOpacity = 0.8, smoothFactor = 0.5, # make it nicer
                  popup = t_popup)  # add popup
              })
              
              })
            
            
        
    }