r - 如何根据 R Shiny 中 Leaflet map 的输入来过滤数据表?

标签 r shiny leaflet

我正在使用shiny制作一个仪表板,其中包含传单 map 和数据表。我希望能够单击 map 上的多边形(即特定县),将该县存储为 react 值,然后过滤数据表以仅显示该县的结果。

我还希望数据表在没有单击任何多边形的情况下默认显示所有行,如果未选择多边形则返回显示所有行。

这是我创建的一个基本工作示例。我可以单击 map 并获取正确的县,但在 click_county 中存储该值时似乎遇到问题。

lapply(c('data.table','dplyr','ggplot2','shiny','shinydashboard','leaflet','DT',
         'USAboundaries','sf'), library, character.only = TRUE)

ca_counties <- USAboundaries::us_counties(states = 'CA')

parcels <- structure(list(county = c("Yuba", "Sacramento", "Inyo"), num.parcels = c(27797L, 
                                                                                    452890L, 6432L)), row.names = c(NA, -3L), class = "data.frame")

parcels <- st_as_sf(left_join(parcels, ca_counties[,c('name')], by = c("county" = "name")))
parcels_df <- parcels
parcels_df$geometry <- NULL

#====================================================================================================

ui <- dashboardPage(
  skin = 'green',
  dashboardHeader(),
  dashboardSidebar(sidebarMenu(
    menuItem('Use of Force Incidents', tabName = 'dallas_maps', icon = icon('city'))
  )),
  dashboardBody(tabItems(
    #===== Dallas Map Tab =====#
    tabItem(tabName = 'dallas_maps',
            fluidRow(
              box(
                width = 12, collapsible = T,
                title = 'Dallas County Census Block Groups',
                solidHeader = T, status = 'primary',
                leafletOutput('parcels_map')
              )
            ),
            fluidRow(
              box(
                width = 12, collapsible = T,
                title = 'Use of Force Incidents, 2014 - 2016',
                solidHeader = T, status = 'primary',
                dataTableOutput('parcels_table')
              )
            )
    )
  ))
)

#====================================================================================================

server <- function(input, output, session) {
  #===== Dallas Map Tab =====#
  # Map of Census block groups
  output$parcels_map <- renderLeaflet({
    bins <- c(1, 10000, 50000, 100000, 500000, 600000)
    pal <- colorBin("Blues", domain = parcels$num.parcels, bins = bins)
    
    labels <- sprintf(
      "<strong>%s County</strong><br/>
      Parcels: %g<br/>",
      parcels$county, parcels$num.parcels
      ) %>% lapply(htmltools::HTML)
    
    leaflet(parcels) %>%
      setView(-119, 37.9, 6) %>%
      addTiles() %>%
      addPolygons(
        layerId = ~county,
        fillColor = ~pal(num.parcels),
        weight = 2,
        opacity = 1,
        color = 'black',
        dashArray = '2',
        fillOpacity = 0.7,
        highlightOptions = highlightOptions(color = "red", weight = 3,
                                            bringToFront = TRUE),
        label = labels,
        labelOptions = labelOptions(
          style = list("font-weight" = "normal", padding = "4px 8px"),
          textsize = "15px",
          direction = 'auto')) %>%
      addLegend(pal = pal, values = ~num.parcels, opacity = 0.7, title = "Number of Parcels",
                position = "bottomleft")
  })
  
  click_county <- reactiveVal()
  
  observeEvent(input$parcels_map_shape_click, {
    # Capture the info of the clicked polygon
    click_county <- input$parcels_map_shape_click$id
  })
  
  print(click_county)
  
  # Parcels data table
  output$parcels_table <- DT::renderDataTable({
    DT::datatable(parcels_df,
                  # colnames = c(''),
                  options = list(lengthMenu = c(10, 25, 50, 100),
                                 pageLength = 10,
                                 columnDefs = list(list(className = 'dt-center', targets = '_all'))),
                  filter = 'top')
  })
  
}

shinyApp(ui, server)

我已经尝试过类似的方法来呈现数据表,这样我就可以默认获取所有行,并且在单击 map 时仅获取过滤后的行:

# Parcels data table
output$parcels_table <- DT::renderDataTable({
  if (is.null(click_county())) {
    DT::datatable(parcels_df,
                  options = list(lengthMenu = c(10, 25, 50, 100),
                                 pageLength = 10,
                                 columnDefs = list(list(className = 'dt-center', targets = '_all'))),
                  filter = 'top')
  }
  else if (!is.null(click_county())) {
    DT::datatable(parcels_df[parcels_df$county == click_county(),],
                  options = list(lengthMenu = c(10, 25, 50, 100),
                                 pageLength = 10,
                                 columnDefs = list(list(className = 'dt-center', targets = '_all'))),
                  filter = 'top')
  }
})

最佳答案

您需要使用语法 click_county(input$parcels_map_shape_click$id)reactiveVal 赋值。

在这里,我通过重新单击同一县来删除过滤器,因为我可以找到在县外单击的事件:

  observeEvent(input$parcels_map_shape_click, {
    # Capture the info of the clicked polygon
    if(!is.null(click_county()) && click_county() == input$parcels_map_shape_click$id)
      click_county(NULL)     # Reset filter
    else
      click_county(input$parcels_map_shape_click$id)
  })

  # Parcels data table
  output$parcels_table <- DT::renderDataTable({
    DT::datatable( 
      if(is.null(click_county())) 
        parcels_df    # Not filtered
      else 
        parcels_df %>% filter( county==click_county())
        )
  })

关于r - 如何根据 R Shiny 中 Leaflet map 的输入来过滤数据表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64361604/

相关文章:

r - 从 R 中的函数中捕获警告并仍然获得它们的返回值?

r - 选择级别数等于 1 的分类变量

c++ - 如何使用 Rcpp 处理 R 和 C++ 中调用约定的不匹配?

css - 在 Shiny 中,如何为范围 slider 的两个按钮使用不同的颜色?

r - 在 Shiny 的 rhandsontable 单元格中插入控制输入和 HTML 小部件

javascript - 如何创建依赖于普通变量、函数或逻辑的 ember 属性?

r - 维恩图 : How to hide % overlap labels?

r - 如何在 Shiny 中单击添加/保留任意数量的绘图层

javascript - 传单 - 我似乎无法让基本示例发挥作用

javascript - 如何使用javascript将 "screenshot"传单映射到base64?