如何在Shiny应用的mapview/leaflet中实现单个点位的可视化
问题描述
我有一个大型数据集,这里用3条记录构建了最小化可复现示例。目前我的Leaflet地图能同时显示全部3个站点,但需求是点击下拉选择框时,每次仅展示单个站点(比如只显示site2)。我知道switch函数,但不清楚怎么在这个场景里实现。附上可复现代码和数据如下:
数据预览
Location geometry * <chr> <POINT [°]> 1 site1 (-115.1682 44.3943) 2 site2 (-114.0403 44.6845) 3 site3 (-114.8841 44.1533)
原可复现代码
library(shiny) library(mapview) library(writexl) library(tidyverse) library(leaflet) locations <- c("site1", "site2", "site3") ui <- fluidPage( #titlePanel("Screwtraps and temp logger in Idaho"), sidebarLayout( sidebarPanel( selectInput(inputId = "site", label = "Select Site", choices = locations)), mainPanel(leafletOutput("map",width = "100%", height="87vh") ) ) ) server <- function(input, output, session) { session$onSessionEnded(function() { stopApp() }) output$map<-renderLeaflet({ #Select all sites final <- mapview(site, col.regions='red', alpha=1) final@map #How can I render my map with only the selected site from the userInput dropdown? }) } shinyApp(ui, server)
数据集结构
site <- structure(list(Location = c("site1", "site2", "site3"), geometry = structure(list( structure(c(-115.1682, 44.3943), class = c("XY", "POINT", "sfg")), structure(c(-114.0403, 44.6845), class = c("XY", "POINT", "sfg")), structure(c(-114.8841, 44.1533), class = c("XY", "POINT", "sfg"))), n_empty = 0L, precision = 0, crs = structure(list( input = "EPSG:4326", 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 USAGE[\n SCOPE[\"Horizontal component of 3D system.\"],\n AREA[\"World.\"],\n BBOX[-90,-180,90,180]],\n ID[\"EPSG\",4326]]"), class = "crs"), bbox = structure(c(xmin = -115.1682, ymin = 44.1533, xmax = -114.0403, ymax = 44.6845), class = "bbox"), class = c("sfc_POINT", "sfc"))), row.names = c(NA, 3L), sf_column = "geometry", agr = structure(c(Location = NA_integer_), class = "factor", .Label = c("constant", "aggregate", "identity")), class = c("sf", "tbl_df", "tbl", "data.frame" )) site
示意图

解决方案
不需要用switch函数,直接根据下拉框输入筛选sf数据集即可。核心是在renderLeaflet中,根据input$site过滤site数据,只保留选中的站点,再用mapview渲染。
修改后的server部分代码如下:
server <- function(input, output, session) { session$onSessionEnded(function() { stopApp() }) output$map<-renderLeaflet({ # 筛选选中的站点 selected_site <- site %>% filter(Location == input$site) # 仅渲染选中的站点 final <- mapview(selected_site, col.regions='red', alpha=1) final@map }) }
补充说明
- 你的数据是sf格式,用
dplyr::filter可轻松根据Location列匹配下拉框输入值input$site - 每次下拉框选择变化时,
renderLeaflet会自动重新执行,渲染对应的单个站点 - 如果非要用switch函数,也可以这么写(但筛选方式更简洁):
output$map<-renderLeaflet({ selected_site <- switch(input$site, "site1" = site %>% filter(Location == "site1"), "site2" = site %>% filter(Location == "site2"), "site3" = site %>% filter(Location == "site3")) final <- mapview(selected_site, col.regions='red', alpha=1) final@map })
内容的提问来源于stack exchange,提问作者Salvador
相关产品推荐
相关产品推荐

