filtering data reactively to generate maps

纵然是瞬间 提交于 2021-01-28 11:01:57

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!