问题
In working with a map in shiny using mapview
, I've been flummoxed by reactives and trying to make my map dynamically update. Here is a reproducible example that doesn't work properly, despite being designed using principles from other SO answers:
#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
library(sf)
library(mapview)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Test of Mapview Selective Viewing"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("county", "County Name",
choices = c("All", levels(franconia$NAME_ASCI)),
selected = "All"
)
),
# Show a plot of the generated distribution
mainPanel(
mapviewOutput("mapPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
fran <- reactive({
f <- franconia
if(input$county != "All") f <- franconia %>% filter(NAME_ASCI == input$county)
f
})
output$mapPlot <- renderMapview({
#get the data
f <- isolate(fran())
#generate a map
mapview(f, zcol = "NAME_ASCI")
})
}
# Run the application
shinyApp(ui = ui, server = server)
This works, but the map will not update. I've tried putting in an action button - and putting input$button before the isolate statement, but, that causes the whole thing to throw an error.
I want to either see everything or a single county.
Any thoughts on what is missing/wrong here? I'm somewhat new to shiny and dealing with reactives!
回答1:
Usage of renderMapview
seems to be somehow "discouraged" (see https://github.com/r-spatial/mapview/issues/160#issuecomment-398130788; https://github.com/r-spatial/mapview/issues/58). You should instead use renderLeaflet
on the @map attribute of the mapview
object. This should work:
library(shiny)
library(sf)
library(mapview)
library(leaflet)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Test of Mapview Selective Viewing"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("county", "County Name",
choices = c("All", levels(franconia$NAME_ASCI)),
selected = "All"
)
),
# Show a plot of the generated distribution
mainPanel(
mapviewOutput("mapPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
fran <- reactive({
f <- franconia
if(input$county != "All") f <- f <- franconia[franconia$NAME_ASCI == input$county, ]
f
})
output$mapPlot <- renderLeaflet({
#get the data
f <- fran()
#generate a map
mapview(f, zcol = "NAME_ASCI")@map
})
}
# Run the application
shinyApp(ui = ui, server = server)
(Note that I also had to remove the isolate
call as suggested by @Kent Johnson)
HTH!
回答2:
Put the map output inside observe
and get rid of the isolate
. isolate
is preventing the update, observe
lets you remove it:
observe({
output$mapPlot <- renderMapview({
f <- fran()
mapview(f, zcol = "NAME_ASCI")
})
})
回答3:
Generally, you shouldn't nest a render output inside an observe, you can split them up like this:
mapPlot <- reactive(mapview(fran(), zcol = "NAME_ASCI"))
output$mapPlot <- renderMapview(mapPlot())
回答4:
@ibusett is correct but this is the working code including the subsetting (their code only works with input == All).
Edit: they updated their code to match my general subset, but you can use dplyr::filter on sf objects (as they mention).
library(sf)
library(mapview)
library(leaflet)
ui <- fluidPage(
# Application title
titlePanel("Test of Mapview Selective Viewing"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("county", "County Name",
choices = c("All", levels(franconia$NAME_ASCI)),
selected = "All"
)
),
# Show a plot of the generated distribution
mainPanel(
mapviewOutput("mapPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
fran <- reactive({
f <- franconia
if(input$county != "All"){
f <- franconia[franconia$NAME_ASCI == input$county, ]
}
f
})
output$mapPlot <- renderLeaflet({
#get the data
f <- fran()
#generate a map
mapview(f, zcol = "NAME_ASCI")@map
})
}
# Run the application
shinyApp(ui = ui, server = server)
来源:https://stackoverflow.com/questions/59585109/filtering-data-reactively-to-generate-maps