【问题标题】:filtering data reactively to generate maps反应性地过滤数据以生成地图
【发布时间】:2020-04-22 09:41:04
【问题描述】:

在使用mapview 处理闪亮的地图时,我被反应式弄糊涂了,并试图让我的地图动态更新。这是一个无法正常工作的可重现示例,尽管是使用其他 SO 答案中的原则设计的:

#
# 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)

这可行,但地图不会更新。我尝试放入一个操作按钮 - 并将 input$button 放在隔离语句之前,但是,这会导致整个事情抛出一个错误。

我想查看全部或单个县。

关于这里缺少/错误的任何想法?我对闪亮和处理反应有些陌生!

【问题讨论】:

    标签: r shiny reactive-programming r-mapview


    【解决方案1】:

    @ibusett 是正确的,但这是包含子集的工作代码(他们的代码仅适用于输入 == 全部)。

    编辑:他们更新了代码以匹配我的一般子集,但您可以在 sf 对象上使用 dplyr::filter(正如他们所提到的)。

    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)
    

    【讨论】:

      【解决方案2】:

      renderMapview 的使用似乎有点“不鼓励”(请参阅​​https://github.com/r-spatial/mapview/issues/160#issuecomment-398130788;https://github.com/r-spatial/mapview/issues/58)。您应该在mapview 对象的@map 属性上使用renderLeaflet。这应该有效:

      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)
      

      (请注意,我还必须按照@Kent Johnson 的建议删除isolate 调用)

      HTH!

      【讨论】:

      • 请注意,filter() 不适用于您编写的 sf 对象。我发布了一个小修复,但您应该得到最佳答案。
      • 更改为:f
      • @CarlosMercado filter 适用于 sf 对象-...前提是 dplyr::filter... 感谢您指出这一点!我使用您的建议进行了修改,因为它更“通用”。
      【解决方案3】:

      一般情况下,你shouldn't nest a render output inside an observe,可以这样拆分:

      mapPlot <- reactive(mapview(fran(), zcol = "NAME_ASCI"))
      
      output$mapPlot <- renderMapview(mapPlot())
      

      【讨论】:

      • 当我尝试这个时我得到Operation not allowed without an active reactive context.。
      • 这可能是mapview 错误;如果我将应用程序更改为直接使用leaflet,则以这种方式编写时它可以工作。
      • 我在这里提交了mapview 问题:github.com/r-spatial/mapview/issues/254
      • @KentJohnson。这很有趣,谢谢。我想知道renderMapView,expr &lt;- mapview2leaflet(expr)中是否是这个。它尝试在任何闪亮的exprToFunction 业务之前访问反应式表达式
      • @SmokeyShakers 这是我的猜测。我不知道如何解决它。
      【解决方案4】:

      把地图输出放在observe里面,去掉isolate。 isolate 阻止更新,observe 允许您删除它:

        observe({
          output$mapPlot <- renderMapview({
            f <- fran()
            mapview(f, zcol = "NAME_ASCI")
          })
        })
      

      【讨论】:

      • 不 - 仍然没有更新。
      • 不知道该说什么,当我用上面的替换你的output$mapPlot &lt;- ...时它对我有用。
      猜你喜欢
      • 2022-08-17
      • 2019-07-17
      • 2019-02-07
      • 1970-01-01
      • 2021-01-01
      • 2022-01-24
      • 2022-09-29
      • 2021-04-24
      • 1970-01-01
      相关资源
      最近更新 更多