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

如何在Shiny Apps中实现产品层级下拉筛选控件?

在Shiny Apps中实现层级联动产品筛选器

核心思路

用Shiny的updateSelectizeInput实现下拉框联动,根据上一级筛选结果动态更新下一级选项。针对6800个产品的场景,优先用selectizeInput(支持搜索、性能更优)替代原生selectInput,解决大量选项的选择效率问题。

步骤实现

1. 准备层级数据

假设你的数据包含多级分类字段(如一级分类、二级分类、6位产品编码、产品名称),先整理成结构化格式。这里模拟一份适配需求的示例数据:

library(dplyr)
library(tidyr)

# 模拟6800条层级产品数据
set.seed(123)
product_data <- tibble(
  level1 = sample(paste0("大类", 1:5), 6800, replace = TRUE),
  level2 = paste0(level1, "-", sample(paste0("小类", 1:10), 6800, replace = TRUE)),
  product_code = sprintf("%06d", 1:6800),
  product_name = paste0("产品", product_code)
)

# 预缓存层级映射,避免重复计算提升性能
level1_options <- unique(product_data$level1)
level2_map <- product_data %>% 
  group_by(level1) %>% 
  summarise(options = unique(level2)) %>% 
  pivot_wider(names_from = level1, values_from = options)
product_map <- product_data %>% 
  group_by(level2) %>% 
  summarise(options = setNames(product_code, product_name)) %>% 
  pivot_wider(names_from = level2, values_from = options)

2. UI部分构建

使用selectizeInput创建三级联动下拉框,产品级开启搜索功能方便快速定位:

library(shiny)

ui <- fluidPage(
  titlePanel("层级产品筛选"),
  sidebarLayout(
    sidebarPanel(
      selectizeInput("level1", "一级分类", choices = level1_options, selected = level1_options[1]),
      selectizeInput("level2", "二级分类", choices = NULL),
      selectizeInput("product", "产品(6位编码)", choices = NULL, 
                     options = list(placeholder = "输入名称/编码搜索", maxOptions = 100))
    ),
    mainPanel(
      verbatimTextOutput("selected_info")
    )
  )
)

3. Server联动逻辑

通过observeEvent监听上一级输入变化,动态更新下一级选项:

server <- function(input, output, session) {
  # 监听一级分类,更新二级分类选项
  observeEvent(input$level1, {
    updateSelectizeInput(session, "level2", 
                         choices = level2_map[[input$level1]], 
                         selected = level2_map[[input$level1]][1])
  }, ignoreInit = FALSE)
  
  # 监听二级分类,更新产品选项
  observeEvent(input$level2, {
    if (!is.null(input$level2)) {
      updateSelectizeInput(session, "product", choices = product_map[[input$level2]])
    } else {
      updateSelectizeInput(session, "product", choices = NULL)
    }
  }, ignoreInit = FALSE)
  
  # 输出选中的产品详情
  output$selected_info <- renderPrint({
    if (!is.null(input$product)) {
      product_data %>% 
        filter(product_code == input$product) %>% 
        select(level1, level2, product_code, product_name)
    }
  })
}

shinyApp(ui, server)

性能优化建议

  • 预缓存层级映射:提前计算各层级的选项对应关系,避免每次联动时重复过滤全量数据,加快响应速度。
  • 开启搜索功能:用户可通过输入产品名称或编码快速定位,无需滚动6800个选项。
  • 限制显示选项数:通过maxOptions控制下拉框显示的最大选项数,减少DOM元素渲染压力。
  • 超大数据量适配:如果产品数远超6800,可使用shinyWidgets::pickerInput或实现selectize的远程加载功能,异步拉取匹配选项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:10:03