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

R Shiny中子图无对应数据时用主图数据填充并显示‘Other’类别

解决方案

核心思路是在子图的数据源中,为Jewel门店补充指定的"Other"分类数据,确保筛选Vegetable/Fruit时能显示数值800的柱状条。只需修改server部分的store_reactive_2反应式对象即可实现需求:

store_reactive_2 <- reactive({
  # 先获取原始筛选数据
  filtered_data <- store_data %>%
    filter(Grocery_Store %in% input$store) %>%
    filter(Food_Filter %in% input$food_subcategory)
  
  # 检查是否需要添加Jewel的Other数据
  if ("Jewel" %in% input$store && input$food_subcategory %in% c("Vegetable", "Fruit")) {
    # 构造Jewel的补充行
    jewel_other <- tibble(
      Grocery_Store = "Jewel",
      Sales = 800,
      Food_Main = "Other",
      Food_Filter = input$food_subcategory
    )
    # 合并原始数据和补充数据
    filtered_data <- bind_rows(filtered_data, jewel_other)
  }
  
  filtered_data
})

完整修改后的代码

library(tidyverse)
library(plotly)
library(shiny)
library(shinydashboard)
library(shinyWidgets)


store_data <- tibble(
  Whole_Foods = c(1000, 500, 500, 1000, 500, 500),
  Kroger = c(700, 300, 400, 700, 300, 400),
  Jewel = c(800, 0, 0, 800, 0, 0),
  Food_Main = c("Vegetable", "Lettuce", "Potato", "Fruit", "Lemon", "Watermelon"),
  Food_Filter = c("None", "Vegetable", "Vegetable", "None", "Fruit", "Fruit")
  
)


store_data <- store_data %>%
  reshape2::melt(measure.vars = c("Whole_Foods", "Kroger", "Jewel"),
                 variable.name = "Grocery_Store") %>%
  mutate(value = value %>% as.numeric()) %>%
  rename(Sales = value)


ui <- fluidPage(
  selectInput(inputId = "store",
              label = "Grocery Store",
              multiple = TRUE,
              choices = unique(store_data$Grocery_Store),
              selected = unique(store_data$Grocery_Store)),
  selectInput(inputId = "food_subcategory",
              label = "Food Type",
              choices = c("Vegetable", "Fruit")),
  plotlyOutput("food_level", height = 200),
  plotlyOutput("filter_level", height = 200),
  uiOutput('back'),
  uiOutput("back1")
)


server <- function(input, output, session) {
  
  
  food_filter <- reactiveVal()
  type_filter <- reactiveVal()
  
  
  observeEvent(event_data("plotly_click", source = "food_level"), {
    food_filter(event_data("plotly_click", source = "food_level")$x)
    type_filter(NULL)
  })
  
  
  observeEvent(event_data("plotly_click", source = "filter_level"), {
    type_filter(
      event_data("plotly_click", source = "filter_level")$x
    )
  })
  
  
  store_reactive <- reactive({
    store_data %>%
      filter(Food_Filter ==  "None") %>%
      filter(Grocery_Store %in% input$store)
  })
  
  
  output$food_level <- renderPlotly({
    store_reactive() %>% 
      plot_ly(
        x = ~Grocery_Store,
        y = ~Sales,
        color = ~Food_Main,
        source = "food_level",
        type = "bar"
      ) %>% 
      layout(barmode = "stack", showlegend = T)
  })
  
  
  store_reactive_2 <- reactive({
    # 先获取原始筛选数据
    filtered_data <- store_data %>%
      filter(Grocery_Store %in% input$store) %>%
      filter(Food_Filter %in% input$food_subcategory)
    
    # 检查是否需要添加Jewel的Other数据
    if ("Jewel" %in% input$store && input$food_subcategory %in% c("Vegetable", "Fruit")) {
      # 构造Jewel的补充行
      jewel_other <- tibble(
        Grocery_Store = "Jewel",
        Sales = 800,
        Food_Main = "Other",
        Food_Filter = input$food_subcategory
      )
      # 合并原始数据和补充数据
      filtered_data <- bind_rows(filtered_data, jewel_other)
    }
    
    filtered_data
  })
  
  
  output$filter_level <- renderPlotly({
    if (is.null(food_filter())) return(NULL)
    
    store_reactive_2() %>% 
      plot_ly(
        x = ~Grocery_Store,
        y = ~Sales,
        color = ~Food_Main,
        source = "food_level",
        type = "bar"
      ) %>% 
      layout(barmode = "stack", showlegend = T)
  })
  
  
  output$back <- renderUI({
    if (!is.null(food_filter()) && is.null(type_filter())) {
      actionButton("clear", "Back", icon("chevron-left"))
    }
  })
  
  
  output$back1 <- renderUI({
    if (!is.null(type_filter())) {
      actionButton("clear1", "Back", icon("chevron-left"))
    }
  })
  
  
  observeEvent(input$clear,
               food_filter(NULL))
  observeEvent(input$clear1,
               type_filter(NULL))
  
}


shinyApp(ui, server)

关键说明

  • 当用户选择的门店包含Jewel,且Food Type为Vegetable或Fruit时,自动添加一条Jewel的记录,Sales设为800,Food_Main标注为"Other"
  • 使用bind_rows将补充数据与原始筛选数据合并,保证子图能正确渲染Jewel的柱状条
  • 逻辑判断确保只有在符合条件时才添加数据,不影响其他场景的正常展示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:01:05