You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shiny交互式时间序列感染率地图无输出问题求助

Shiny交互式时间序列感染率地图无输出问题求助

看起来你遇到了Shiny app里地图死活渲染不出来的麻烦——手动过滤数据能正常出图,一放到反应式逻辑里就只剩年月选择器,连个报错都没有,这种情况确实挺磨人的!我帮你分析下大概率出问题的地方,再给你调整后的完整代码试试。

先聊聊可能的核心坑点

你贴的代码没写完server部分,这应该是关键问题:

  1. 反应式数据集定义缺失:你大概率没正确基于输入的年月生成过滤后的反应式数据,或者过滤逻辑有漏洞
  2. 日期匹配逻辑不对:如果Date列是日期类型,直接用输入的年月数字对比可能匹配不上,得用工具函数提取日期里的年/月再对比
  3. sf对象属性丢失:left_join后的TS_PI是带空间属性的sf对象,反应式处理时要确保它的geometry列没丢
  4. 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)

几个关键的注意事项

  1. 替换感染率列名:代码里的prevalence是我假设的,你要换成你CSV里实际的感染率字段名,比如PI_rate之类的
  2. 用数据里的实际年份:我把year选择器的选项改成了从ts_brazil$Date里提取的唯一年份,避免选到数据里没有的年份导致过滤后无数据
  3. req()函数的作用:它能确保只有当输入的年月都存在、反应式数据加载完成时才执行后续代码,避免因空数据导致的无输出
  4. 排查小技巧:如果还是出不来,可以把代码里注释的print(nrow(filtered_data()))打开,启动app后看控制台输出的行数:
    • 如果是0:说明你选的年月在数据里没有对应记录,检查数据里的日期范围
    • 如果有行数:说明数据没问题,可能是fill映射的列名错了,或者geom_sf()的用法不对

备注:内容来源于stack exchange,提问作者Lavacave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 12:53:14