Shiny中Leaflet点击多边形子集表格报错及替代库咨询
解决Shiny+Leaflet点击多边形展示表格的错误及备选地图库
错误原因及修复方案
你遇到的is.finite: default method not implemented for type 'list'错误,本质是**renderTable无法直接处理包含几何列(list类型)的sf对象**——sf数据框里的geometry列是复杂的列表结构,表格渲染函数无法解析这种类型。同时你的数据集里所有行的ac_code都是259,用它作为layerId会导致点击任意多边形都返回全部数据,无法区分不同区域。
修复后的完整代码
library(shiny) library(leaflet) library(dplyr) library(sf) # 数据集(保持你提供的databad不变) databad<-structure(list(ac_code = c(259L, 259L, 259L), booth_no = 1:3, state = c("West Bengal", "West Bengal", "West Bengal"), ac_name = c("Khandaghosh", "Khandaghosh", "Khandaghosh"), voteshare.IND = c(0.01, 0, 0.01), voteshare.BMUP = c(0.01, 0, 0), voteshare.CPM = c(0.58, 0.31, 0.25), voteshare.AITC = c(0.33, 0.52, 0.57), voteshare.BJP = c(0.06, 0.13, 0.11), voteshare.INC = c(0, 0.02, 0.05), voteshare.BSP = c(0, 0, 0.01), voteshare.SUCI = c(0, 0.01, 0.01), nn_hospital = c("Khundkuri Hospital", "Khundkuri Hospital", "Mankar Rural Hospital"), distance_nn_hospital = c(8949.68646563084, 17217.1419457099, 16939.2318150416), nn_school = c("বর্ধমান টাউন স্কুল", "বর্ধমান টাউন স্কুল", "Guskara Girls High School" ), distance_nn_school = c(16834.9368635036, 24332.8584456302, 19846.4525464748), nn_bank = c("contai", "contai", "Allahabad Bank" ), distance_nn_bank = c(13959.9950089655, 20598.4763042432, 19688.6296071566), nn_atm = c("ING Bank", "ING Bank", "ING Bank" ), distance_nn_atm = c(55404.6817200836, 47524.5016641311, 45106.1556369373), voteshare.JMM = c(NA_real_, NA_real_, NA_real_), voteshare.JDP = c(NA_real_, NA_real_, NA_real_ ), voteshare.CPI.ML..L. = c(NA_real_, NA_real_, NA_real_), voteshare.IUML = c(NA_real_, NA_real_, NA_real_), voteshare.GaAP = c(NA_real_, NA_real_, NA_real_), voteshare.NOTA = c(NA_real_, NA_real_, NA_real_), geometry = structure(list(structure(list(list( structure(c(87.7090902547602, 87.7151753707173, 87.7154550055682, 87.7086421531382, 87.7023431042605, 87.6970612820198, 87.7017218525372, 87.7090902547602, 23.2040982701717, 23.2136143676662, 23.2156954885727, 23.2276541162583, 23.2281630737782, 23.2181646062169, 23.2053620549479, 23.2040982701717), dim = c(8L, 2L)))), class = c("XY", "MULTIPOLYGON", "sfg")), structure(list(list(structure(c(87.6365062737229, 87.6376152918208, 87.6308791550368, 87.625023101282, 87.62345364621, 87.6365062737229, 23.2401534236987, 23.244460158139, 23.2496234950258, 23.2489032619139, 23.2468180156553, 23.2401534236987), dim = c(6L, 2L)))), class = c("XY", "MULTIPOLYGON", "sfg")), structure(list( list(structure(c(87.6586184806029, 87.67258178803, 87.6804334223628, 87.6655208748092, 87.6611300171367, 87.6604474038247, 87.6586184806029, 23.3194136362408, 23.3169136956011, 23.3271416599132, 23.333645873538, 23.3347376687085, 23.3208934817488, 23.3194136362408), dim = c(7L, 2L)))), class = c("XY", "MULTIPOLYGON", "sfg"))), class = c("sfc_MULTIPOLYGON", "sfc" ), precision = 0, bbox = structure(c(xmin = 87.62345364621, ymin = 23.2040982701717, xmax = 87.7154550055682, ymax = 23.3347376687085 ), class = "bbox"), crs = structure(list(input = "WGS 84", wkt = "GEOGCRS[\"WGS 84\",\n DATUM[\"World Geodetic System 1984\",\n ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n LENGTHUNIT[\"metre\",1]]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n CS[ellipsoidal,2],\n AXIS[\"geodetic latitude (Lat)\",north,\n ORDER[1],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n AXIS[\"geodetic longitude (Lon)\",east,\n ORDER[2],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n ID[\"EPSG\",4326]]"), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(ac_code = NA_integer_, booth_no = NA_integer_, state = NA_integer_, ac_name = NA_integer_, voteshare.IND = NA_integer_, voteshare.BMUP = NA_integer_, voteshare.CPM = NA_integer_, voteshare.AITC = NA_integer_, voteshare.BJP = NA_integer_, voteshare.INC = NA_integer_, voteshare.BSP = NA_integer_, voteshare.SUCI = NA_integer_, nn_hospital = NA_integer_, distance_nn_hospital = NA_integer_, nn_school = NA_integer_, distance_nn_school = NA_integer_, nn_bank = NA_integer_, distance_nn_bank = NA_integer_, n_atm = NA_integer_, distance_nn_atm = NA_integer_, voteshare.JMM = NA_integer_, voteshare.JDP = NA_integer_, voteshare.CPI.ML..L. = NA_integer_, voteshare.IUML = NA_integer_, voteshare.GaAP = NA_integer_, voteshare.NOTA = NA_integer_ ), levels = c("constant", "aggregate", "identity"), class = "factor"), row.names = c(NA, 3L), class = c("sf", "data.frame")) # Define the shiny app ui <- fluidPage( leafletOutput("map"), tableOutput("subset_table") ) server <- function(input, output, session) { # Render the leaflet map output$map <- renderLeaflet({ leaflet() %>% addProviderTiles("OpenStreetMap.Mapnik") %>% addPolygons(data = databad, layerId = ~booth_no) # 改用booth_no作为唯一标识 }) # Subset and display the table based on the clicked polygon output$subset_table <- renderTable({ event <- input$map_shape_click if (!is.null(event)) { clicked_layer_id <- event$id subset_data <- databad %>% filter(booth_no == clicked_layer_id) %>% st_drop_geometry() # 移除几何列,转换为普通数据框 subset_data } }) } # Run the app shinyApp(ui, server)
关键修改点
- 替换layerId:用
booth_no替代ac_code,确保每个多边形对应唯一的数据行 - 移除几何列:使用
st_drop_geometry()将sf对象转换为普通data.frame,避免表格渲染函数解析list类型数据
备选交互式地图库
如果Leaflet不符合需求,可选择以下R语言地图库:
- plotly:基于plotly.js,支持空间数据的交互式可视化,点击事件处理灵活,可与Shiny深度联动,适合需要多组件联动的场景
- mapview:专为空间数据设计,默认支持点击、缩放等交互,代码简洁,可快速嵌入Shiny应用
- tmap:支持交互式模式(
tmap_mode("view")),语法直观,适合制作专业级交互式地图 - googleway:调用Google Maps API,支持路况、自定义标记等高级功能,适合依赖谷歌地图服务的场景(需API密钥)
内容的提问来源于stack exchange,提问作者firmo23
相关产品推荐
相关产品推荐

