Shiny交互式时间序列感染率地图无输出问题求助
Shiny交互式时间序列感染率地图无输出问题求助
看起来你遇到了Shiny app里地图死活渲染不出来的麻烦——手动过滤数据能正常出图,一放到反应式逻辑里就只剩年月选择器,连个报错都没有,这种情况确实挺磨人的!我帮你分析下大概率出问题的地方,再给你调整后的完整代码试试。
先聊聊可能的核心坑点
你贴的代码没写完server部分,这应该是关键问题:
- 反应式数据集定义缺失:你大概率没正确基于输入的年月生成过滤后的反应式数据,或者过滤逻辑有漏洞
- 日期匹配逻辑不对:如果Date列是日期类型,直接用输入的年月数字对比可能匹配不上,得用工具函数提取日期里的年/月再对比
- sf对象属性丢失:left_join后的TS_PI是带空间属性的sf对象,反应式处理时要确保它的geometry列没丢
- ggplot映射没对应对:渲染sf地图要用
geom_sf(),而且fill要准确对应你感染率的字段(你代码里没提这个列名,得注意替换)
调整后的完整代码
我补全了你没写完的部分,重点修正了反应式数据和渲染逻辑:
library(geobr) library(sf) library(ggplot2) library(shiny) library(lubridate) # 新增:处理日期更方便 library(dplyr) # 新增:数据过滤用 # 读取并预处理数据 ts_brazil <- read.csv("Time_series_PI.csv") ts_brazil$Date <- dmy(ts_brazil$Date) # 确保Date是日期类型 # 读取南里奥格兰德州的市镇地图数据 all_muni <- read_municipality( code_muni = "RS", year= 2010, showProgress = FALSE ) # 合并数据(注意:确保ts_brazil里的感染率列名是prevalence,不是的话要替换!) TS_PI <- left_join(x=ts_brazil, y= all_muni, by = 'code_muni') # UI部分补全 ui <- fluidPage( sidebarLayout( sidebarPanel( selectInput("year", "Year", choices = unique(year(ts_brazil$Date))), # 从数据里提取实际存在的年份 selectInput("month", "Month", choices = 1:12, selected = 1, # 默认选1月 label = "Month") ), mainPanel( plotOutput("infection_map") # 必须加这个:指定图表输出的位置 ) ) ) # Server部分核心修正 server <- function(input, output) { # 1. 定义反应式过滤数据集:只有当输入的年月都存在时才执行 filtered_data <- reactive({ req(input$year, input$month) # 避免输入未初始化时执行空逻辑 TS_PI %>% filter(year(Date) == as.integer(input$year), # 转成整数匹配日期提取出的年 month(Date) == as.integer(input$month)) }) # 2. 渲染地图:确保反应式数据加载完成再渲染 output$infection_map <- renderPlot({ req(filtered_data()) # 等待数据准备好 # 检查过滤后的数据行数(可以打开控制台看输出,排查是否有数据) # print(nrow(filtered_data())) ggplot(filtered_data()) + geom_sf(aes(fill = prevalence), # 这里替换成你CSV里实际的感染率列名! color = "white", size = 0.1) + # 市镇边界加白色细边 scale_fill_viridis_c(option = "plasma", name = "感染率(%)") + # 配色更直观 labs(title = paste0("南里奥格兰德州牛感染率 - ", input$year, "年", input$month, "月"), x = NULL, y = NULL) + theme_minimal() + theme(plot.title = element_text(hjust = 0.5, size = 14), legend.position = "bottom") }) } # 启动app shinyApp(ui = ui, server = server)
几个关键的注意事项
- 替换感染率列名:代码里的
prevalence是我假设的,你要换成你CSV里实际的感染率字段名,比如PI_rate之类的 - 用数据里的实际年份:我把year选择器的选项改成了从
ts_brazil$Date里提取的唯一年份,避免选到数据里没有的年份导致过滤后无数据 - req()函数的作用:它能确保只有当输入的年月都存在、反应式数据加载完成时才执行后续代码,避免因空数据导致的无输出
- 排查小技巧:如果还是出不来,可以把代码里注释的
print(nrow(filtered_data()))打开,启动app后看控制台输出的行数:- 如果是0:说明你选的年月在数据里没有对应记录,检查数据里的日期范围
- 如果有行数:说明数据没问题,可能是
fill映射的列名错了,或者geom_sf()的用法不对
备注:内容来源于stack exchange,提问作者Lavacave
相关产品推荐
相关产品推荐

