Shiny中mapview绘制Choropleth图同位置点未求均值问题修复
问题根因
你的判断完全正确。当前传入mapview的空间数据是时序长表结构:同一个坐标点对应不同年份、月份的多条气温观测记录。mapview本身不会自动对同位置的重复要素做数值聚合,渲染时上层绘制的要素会直接覆盖下层要素,最终视觉上就只显示数据集最后一条记录的数值。
修复方案
核心修复逻辑是在传入mapview绘图前,先按空间位置对气温值做聚合计算,不要直接把原始长表数据丢给绘图函数。额外建议补充年、月筛选控件,否则直接对40年所有数据求均值没有实际分析意义。
- 第一步:UI端补充时间筛选控件
在原有文件上传控件下方,新增年份、月份选择器,让用户可以指定要查看的时间范围:# 加在sidebarPanel内fileInput控件的下方 selectInput(inputId = "sel_year", label = "选择年份", choices = NULL), selectInput(inputId = "sel_month", label = "选择月份", choices = c("全年" = 0, 1:12), selected = 0) - 第二步:修正Server端数据读取、聚合、渲染逻辑
首先补全shapefile读取逻辑(原代码里的Read_Shapefile未定义,会直接报错),然后新增数据过滤、聚合步骤,最后用聚合后的数据绘图:server = function(input, output, session) { # 读取上传的shapefile Temp_map = reactive({ req(input$filemap) # 从上传的多文件中找到.shp后缀的主文件路径 shp_path = input$filemap$datapath[grep("\\.shp$", input$filemap$name)] st_read(shp_path, quiet = TRUE) }) # 初始化下拉选项 observe({ req(Temp_map()) dff = Temp_map() # 更新年份选项 updateSelectInput(session, "sel_year", choices = sort(unique(dff$year))) # 更新气温变量选项,匹配数据里实际存在的气温字段 updateSelectInput(session, "Temp", choices = names(dff)[grepl("tmean|tmin|tmax", names(dff), ignore.case = T)], selected = "tmean") }) # 按筛选条件聚合空间数据 agg_map_data = reactive({ req(Temp_map(), input$sel_year, input$sel_month, input$Temp) raw_df = Temp_map() # 按选中年份过滤 filter_df = raw_df %>% filter(year == as.integer(input$sel_year)) # 选了具体月份就加月份过滤,选全年就不过滤月份 if (as.integer(input$sel_month) != 0) { filter_df = filter_df %>% filter(month == as.integer(input$sel_month)) } # 按几何位置分组,对选中的气温变量求均值 agg_df = filter_df %>% group_by(geometry) %>% summarise( temp_val = mean(.data[[input$Temp]], na.rm = TRUE), city = first(CITYNAME), .groups = "drop" ) agg_df }) # 渲染地图 output$mapview = renderLeaflet({ req(agg_map_data()) plot_map = mapview( agg_map_data(), zcol = "temp_val", layer.name = input$Temp, col.regions = colorRampPalette(brewer.pal(9, "YlOrRd")), popup = ~paste0("城市: ", city, "<br>气温: ", round(temp_val, 2)) ) plot_map@map }) } - 可选优化
如果你需要绘制面状的分级统计图,可以先准备对应区域的行政边界sf对象,用st_join把气温点数据和行政边界做空间连接,再按行政单元分组聚合气温值后绘图,展示效果会比点要素更符合常规分级统计图的样式。如果不需要时间维度筛选,只要去掉时间过滤的代码,直接对全量数据按几何位置聚合即可。
注意事项
- 聚合计算时必须加
na.rm = TRUE参数,否则数据中存在缺失值会导致整组均值返回NA,出现地图空白的问题。 - 上传shapefile时必须把.shp、.dbf、.shx、.prj等所有同名文件同时选中上传,否则会出现读取失败的问题。
- 如果同位置点的统计需求不是求均值,只要把
summarise里的mean()换成median()、max()等其他统计函数即可。
内容的提问来源于stack exchange,提问作者Ed_Gravy
相关产品推荐
相关产品推荐

