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

R Shiny仪表板图表不显示问题排查求助

问题排查与修复方案

核心问题与解决步骤

  • 重复的Input ID导致组件冲突
    Shiny要求所有输入组件的inputId必须唯一,你的代码中多个radioButtons和downloadButton使用了相同的ID(filetype、dwd),这会导致组件交互失效,甚至阻断图表渲染。需要给每个组件分配唯一ID,比如filetype_line、dwd_line等。

  • 时间序列分解的错误处理
    你将包含两列的数据框整体转为时间序列,decompose处理多列时间序列会生成多列的趋势/季节/残差项,后续无法在Shiny中正常渲染。应仅对demand列创建时间序列:

    tsdata <- ts(BODFrame$demand, frequency = 2, start = min(BODFrame$Time))
    
  • 条件判断的类型不匹配
    selectInput的选项值是字符型("1"/"2"/"3"),但服务器端用数值型判断(input$Models == 1),导致条件永远不成立,分解图无法渲染。建议直接用语义化的字符值匹配,更直观:

    # UI中修改selectInput选项
    selectInput(inputId = "Models",
                label = "Select Model:",
                choices = c("Trend"="trend", "Seasonality"="seasonal", "Noise"="random"),
                selected = "trend")
    # 服务器端用switch简化判断
    output$plot2 <- renderPlot({
      switch(input$Models,
             "trend" = plot(trend, main = "Decomposed Trend - BOD"),
             "seasonal" = plot(seasonal, main = "Decomposed Seasonality - BOD"),
             "random" = plot(random, main = "Decomposed Noise - BOD")
      )
    })
    
  • 直方图的ggplot语法错误
    直方图中y = ..Demand..是错误用法,..xxx..仅用于ggplot内置统计量(如..count..),这里无需手动指定y轴,直接映射x即可:

    output$hist <- renderPlot({
      ggplot(data = BODFrame) + 
        geom_histogram(bins = 6, breaks = c(1:7), mapping = aes(x = Time),
                       col = "cadetblue4", fill = "cadetblue4", alpha = 0.5) + 
        theme_ipsum() + 
        ggtitle("BOD (mg/1) vs Time Histogram")
    })
    

修复后的完整代码

library(shiny)
library(shinythemes)
library(tidyverse)
library(ggplot2)
library(DT)
library(forecast)
library(fpp)
library(tsbox)
library(hrbrthemes)

# 数据预处理</think_never_used_51bce0c785ca2f68081bfa7d91973934>
data(BOD)
BODFrame <- data.frame(BOD)
# 仅对demand列创建时间序列
tsdata <- ts(BODFrame$demand, frequency = 2, start = min(BODFrame$Time))
ddata <- decompose(tsdata, "multiplicative")
seasonal <- ddata$seasonal
trend <- ddata$trend
random <- ddata$random

# 修正预测对象:基于demand列构建ARIMA模型
forecastframe <- auto.arima(BODFrame$demand)
myforecastframe <- forecast(forecastframe, level=c(60), h = 12)

# UI部分
ui <- fluidPage(
  titlePanel("Effect of Time on BOD (mg/1) Levels"),
  navbarPage("Select Tab",
             
             tabPanel("Explore The Data",
                      mainPanel(
                        tabsetPanel(
                          tabPanel("Line Graph", 
                                   plotOutput("line"), 
                                   br(), 
                                   radioButtons("filetype_line", "Select file type", c("png", "jpeg")), 
                                   downloadButton("dwd_line", "Download Graph")),
                          tabPanel("Histogram", 
                                   plotOutput("hist"), 
                                   br(), 
                                   radioButtons("filetype_hist", "Select file type", c("png", "jpeg")), 
                                   downloadButton("dwd_hist", "Download Graph"))
                        )
                      )
             ),
             
             tabPanel("Statistical Decomposition of the Data",
                      sidebarLayout(
                        sidebarPanel(width = 3,
                                     selectInput(inputId = "Models",
                                                 label = "Select Model:",
                                                 choices = c("Trend"="trend", "Seasonality"="seasonal", "Noise"="random"),
                                                 selected = "trend"),
                                     textOutput("text1")
                        ),
                        mainPanel(
                          plotOutput("plot2"),
                          br(), 
                          radioButtons("filetype_decomp", "Select file type", c("png", "jpeg")), 
                          downloadButton("dwd_decomp", "Download Graph")
                        )
                      )
             ),
             tabPanel("Forecasting BOD",
                      mainPanel(
                        plotOutput("Forecast"),
                        br(), 
                        radioButtons("filetype_forecast", "Select file type", c("png", "jpeg")), 
                        downloadButton("dwd_forecast", "Download Graph")
                      )
             )
  )
)

# 服务器逻辑
server <- function(input, output){
  
  output$line <- renderPlot({
    ggplot(BODFrame, aes(x = Time, y = demand)) + 
      geom_line(col = "cadetblue4", size = 2) + 
      theme_ipsum() + 
      ggtitle("BOD (mg/1) vs Time") +
      geom_point(col = "red", size = 3)
  })
  
  output$hist <- renderPlot({
    ggplot(data = BODFrame) + 
      geom_histogram(bins = 6, breaks = c(1:7), mapping = aes(x = Time),
                     col = "cadetblue4", fill = "cadetblue4", alpha = 0.5) + 
      theme_ipsum() + 
      ggtitle("BOD (mg/1) vs Time Histogram")
  })
  
  output$plot2 <- renderPlot({
    switch(input$Models,
           "trend" = plot(trend, main = "Decomposed Trend - BOD"),
           "seasonal" = plot(seasonal, main = "Decomposed Seasonality - BOD"),
           "random" = plot(random, main = "Decomposed Noise - BOD")
    )
  })
  
  output$Forecast <- renderPlot({
    plot(myforecastframe, main = "Forecasted Level of BOD (mg/1)")
  })
  
  output$text1 <- renderText({
    switch(input$Models,
           "trend" = "The increasing or decreasing value of BOD in the series",
           "seasonal" = "The repeating short term cycle of the BOD series.",
           "random" = "The random variation in the BOD series."
    )
  })
  
  # 折线图下载示例(其余下载逻辑可参照扩展)
  output$dwd_line <- downloadHandler(
    filename = function() {
      paste("line_plot.", input$filetype_line, sep = "")
    },
    content = function(file) {
      ggsave(file, plot = ggplot(BODFrame, aes(x = Time, y = demand)) + 
               geom_line(col = "cadetblue4", size = 2) + 
               theme_ipsum() + 
               ggtitle("BOD (mg/1) vs Time") +
               geom_point(col = "red", size = 3),
             device = input$filetype_line)
    }
  )
}

shinyApp(ui = ui, server = server)

内容的提问来源于stack exchange,提问作者NoobDataAnalyst

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:35:33