R Shiny中能否使用selectizeGroupUI筛选sf简单要素对象?
问题原因
你遇到的报错确实是shinyWidgets::selectizeGroupServer的特性导致的:该模块为了实现双向关联过滤逻辑,会自动将输入的所有数据转换为data.table格式,完全丢失sf对象的类属性和空间元信息,因此leaflet的addPolylines无法识别普通data.frame类型的输入,触发类型不匹配报错。
另外你现有构造线串的代码存在两处错误:一是坐标顺序写反(sf要求x/经度在前,y/纬度在后),二是构造矩阵时误将终点纬度写为了终点经度,会导致路径绘制异常。
解决方案
只需要在调用过滤后的数据时,用sf::st_as_sf()将其重新转回sf对象即可,同时修正线串构造逻辑,修改后的完整可运行代码如下:
library(tidyverse) library(sf) library(shiny) library(shinyWidgets) library(leaflet) # 生成含几何数据的表 geo_data <- structure(list(idx = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), start_lat = c(33.40693,33.64672, 33.57127, 33.42848, 33.54936, 33.53418, 33.60399, 33.49554,33.5056, 33.61696), start_long = c(-112.0298, -111.9255, -112.049,-112.0998, -112.0912, -112.0911, -111.9273, -111.9687, -112.0563, -111.9866), end_lat = c(33.40687, 33.64776, 33.57125, 33.42853,33.54893, 33.53488, 33.60401, 33.49647, 33.5056, 33.61654), end_long = c(-112.0343,-111.9303, -112.0481, -112.0993, -112.0912, -112.0911, -111.931,-111.9711, -112.0541, -111.986)), row.names = c(NA, -10L), spec = structure(list(cols = list(idx = structure(list(), class = c("collector_double","collector")), start_lat = structure(list(), class = c("collector_double", "collector")), start_long = structure(list(), class = c("collector_double", "collector")), end_lat = structure(list(), class = c("collector_double", "collector")), end_long = structure(list(), class = c("collector_double","collector"))), default = structure(list(), class = c("collector_guess","collector")), delim = ","), class = "col_spec"),class = c("data.table","data.frame")) geo_data<- setDT(geo_data) # 修正线串构造逻辑:坐标顺序为经度在前、纬度在后,替换错误的end_long为end_lat geo_data <- geo_data[ , { geometry <- sf::st_linestring(x = matrix(c(start_long, start_lat, end_long, end_lat), ncol = 2, byrow = TRUE)) geometry <- sf::st_sfc(geometry, crs = 4326) # 明确指定WGS84坐标系 geometry <- sf::st_sf(geometry = geometry) } , by = idx ] # 生成过滤用维度表,关联几何数据后转sf table <- structure(list(idx = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), column1 = c("A", "A", "A", "B", "B", "B", "C", "C", "C", "C"), column2 = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), row.names = c(NA, -10L), class = c("tbl_df","tbl", "data.frame")) %>% left_join(x = ., y = geo_data, by = "idx", keep = FALSE) sf <- sf::st_as_sf(table) # Shiny应用 ui <- fluidPage( fluidRow( column( width = 10, offset = 1, tags$h3("Filter data with selectize group"), panel( selectizeGroupUI( id = "my-filters", params = list( column1 = list(inputId = "column1", title = "column1:"), column2 = list(inputId = "column2", title = "column2:") ) ), status = "primary" ), leafletOutput(outputId = "map") ) ) ) server <- function(input, output, session) { res_mod <- callModule( module = selectizeGroupServer, id = "my-filters", data = sf, vars = c("column1", "column2")) output$map <- renderLeaflet({ leaflet() %>% addTiles() %>% # 增加默认底图,可根据需要替换 addPolylines(data = st_as_sf(res_mod())) # 将过滤后的数据重新转为sf对象 }) } shinyApp(ui, server)
内容的提问来源于stack exchange,提问作者Biased_Observer
相关产品推荐
相关产品推荐

