Reputation: 81
I am trying to create an app that allows a user to click on a map, press go, and receive a table of values for that point. I have 2 netCDF files that are stored on Dropbox that I access and save as rasterStacks to get the output data.
In my server function I have an observe event for the map click, however when I go to use the value for latitude or longitude later in the server function I get the error "could not find function "clng", with clng being what I saved the click$longitude to.
Any help would be greatly appreciated.
Thanks, Kirby
library(shiny)
library(leaflet)
library(raster)
library(tidyverse)
library(DT)
library(mailR)
# Read NetCDF Files from public share links
if(!exists("ettemp")){
ettemp <- tempfile("et", fileext = ".nc")
}
if(!exists("preciptemp")){
preciptemp <- tempfile("precip", fileext = ".nc")
}
if(!file.exists(ettemp)){
download.file(url = "https://www.dropbox.com/s/uyq9arqgnprxzv1/ET.nc?raw=1",
destfile = ettemp,
mode = "wb")
}
if(!file.exists(preciptemp)){
download.file(url = "https://www.dropbox.com/s/sgmhq8cmth1jd8h/precip.nc?raw=1",
destfile = preciptemp,
mode = "wb")
}
precip_lowres <- stack(preciptemp)
names(precip_lowres) <- month.name
ET_stack <- stack(ettemp)
names(ET_stack) <- month.name
ui <- fluidPage(
leafletOutput("map"),
actionButton("go", "Go"),
DT::dataTableOutput(outputId = "mytable")
)
server <- shinyServer(function(input, output, session) {
output$map <- renderLeaflet({
leaflet() %>%
setView(lat = 35, lng = -100, zoom = 3) %>%
addTiles(options = providerTileOptions(noWrap = TRUE))
})
observeEvent(input$map_click, {
click <- input$map_click
clat <- click$lat
clng <- click$lng
leafletProxy('map') %>%
clearMarkers() %>%
addMarkers(lng=clng, lat=clat,
popup = paste(round(click$lat, 2), round(click$lng, 2)))
})
coordvals <- eventReactive(input$go, {
coords <- data.frame(cbind(clng(), clat()))
coordinates(coords) <- ~ X1 + X2
precip_vals <- data.frame(raster::extract(precip_lowres, coords)) %>%
gather(key = "Month", value = "Precip") %>%
mutate(Precip = round(Precip, 0))
ET_vals <- data.frame(raster::extract(ET_stack, coords)) %>%
gather(key = "Month", value = "ET")
combo_vals <- precip_vals %>%
left_join(ET_vals) %>%
mutate(ET = ET*3)
combo_vals$Month <- factor(combo_vals$Month, levels = month.name)
})
output$mytable <- DT::renderDataTable({
datatable(coordvals())
})
})
shinyApp(ui, server)
Upvotes: 0
Views: 3001
Reputation: 1494
Below I used reactiveValues()
to initialize click
, clat
, and clng
. Might be cleaner to define them as separate reactive()
expressions. Either way, if you want to use them outside of the observeEvent(handlerExpr={})
argument, you should probably define them outside of the observeEvent()
. Use the handlerExpr
to update their values.
library(shiny)
library(leaflet)
library(raster)
library(tidyverse)
library(DT)
library(mailR)
# Read NetCDF Files from public share links
if(!exists("ettemp")){
ettemp <- tempfile("et", fileext = ".nc")
}
if(!exists("preciptemp")){
preciptemp <- tempfile("precip", fileext = ".nc")
}
if(!file.exists(ettemp)){
download.file(url = "https://www.dropbox.com/s/uyq9arqgnprxzv1/ET.nc?raw=1",
destfile = ettemp,
mode = "wb")
}
if(!file.exists(preciptemp)){
download.file(url = "https://www.dropbox.com/s/sgmhq8cmth1jd8h/precip.nc?raw=1",
destfile = preciptemp,
mode = "wb")
}
precip_lowres <- stack(preciptemp)
names(precip_lowres) <- month.name
ET_stack <- stack(ettemp)
names(ET_stack) <- month.name
ui <- fluidPage(
leafletOutput("map"),
actionButton("go", "Go"),
DT::dataTableOutput(outputId = "mytable")
)
server <- shinyServer(function(input, output, session) {
output$map <- renderLeaflet({
leaflet() %>%
setView(lat = 35, lng = -100, zoom = 3) %>%
addTiles(options = providerTileOptions(noWrap = TRUE))
})
clickValues <- reactiveValues(
click=NULL, clat=NULL, clng=NULL)
observeEvent(input$map_click, {
clickValues$click <- input$map_click
clickValues$clat <- click$lat
clickValues$clng <- click$lng
leafletProxy('map') %>%
clearMarkers() %>%
addMarkers(lng=clickValues$clng, lat=clickValues$clat,
popup = paste(round(clickValues$click$lat, 2),
round(clickValues$click$lng, 2)))
})
coordvals <- eventReactive(input$go, {
coords <- data.frame(cbind(clickValues$clng, clickValues$clat))
coordinates(coords) <- ~ X1 + X2
precip_vals <- data.frame(raster::extract(precip_lowres, coords)) %>%
gather(key = "Month", value = "Precip") %>%
mutate(Precip = round(Precip, 0))
ET_vals <- data.frame(raster::extract(ET_stack, coords)) %>%
gather(key = "Month", value = "ET")
combo_vals <- precip_vals %>%
left_join(ET_vals) %>%
mutate(ET = ET*3)
combo_vals$Month <- factor(combo_vals$Month, levels = month.name)
})
output$mytable <- DT::renderDataTable({
datatable(coordvals())
})
})
shinyApp(ui, server)
Upvotes: 2