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

如何基于初始数据集选择动态生成Shiny应用的UI与Server逻辑

实现方案

最优方案是使用Shiny原生conditionalPanel实现页面状态切换,无需引入额外依赖,你原有代码中关于score2的条件隐藏逻辑已经正确,仅需要补充着陆页的控制逻辑即可。

核心修改点

  • 新增着陆页专属区域,应用启动时仅展示数据集选择项和确认按钮
  • 新增主功能区的显示条件,仅当用户确认选择数据集后展示参数配置、表格、下载功能
  • 优化下拉框选项更新逻辑,适配不同数据集的字段差异
  • 增加返回按钮,支持用户回到着陆页重新选择数据集

完整可运行代码

library(dbplyr)
library(dplyr)
library(shiny)
library(shinyWidgets)
library(DT)

df <- read.csv('https://raw.githubusercontent.com/datacfb123/testdata/main/sampleset_df.csv')
df2 <- read.csv('https://raw.githubusercontent.com/datacfb123/testdata/main/sampleset_df.csv')

ui <- fluidPage(
  titlePanel("Sample"),
  # 着陆页面板:未确认数据集时显示
  conditionalPanel(
    condition = "input.confirm_btn == 0",
    wellPanel(
      h2("请选择要使用的数据集"),
      radioButtons("mydata", label = "选择数据框", choices = c("df","df2"), inline=TRUE),
      br(),
      actionButton("confirm_btn", "确认选择,进入配置页", class = "btn-primary")
    )
  ),
  # 主功能面板:确认数据集后显示
  conditionalPanel(
    condition = "input.confirm_btn > 0",
    sidebarLayout(
      sidebarPanel(
        actionButton("back_btn", "返回重新选择数据集"),
        br(),br(),
        selectizeInput("data1", "选择州", choices = NULL),
        selectizeInput("data2", "选择郡", choices = NULL),
        selectizeInput("data3", "选择城市", multiple = TRUE, choices = NULL),
        selectizeInput("data4", "选择人群分类", choices = c("All", unique(df$demo))),
        selectizeInput("data5", "选择状态", choices = c("All", unique(df$status))),
        sliderInput("age", label = h3("选择年龄范围"), 18,
                    35, value = c(18, 20), round = TRUE, step = 1),
        sliderInput("score1", label = h3("选择Score1范围"), min = 0,
                    max = 100, value = c(20,80)),
        conditionalPanel(condition = "input.mydata=='df'",
                         sliderInput("score2", label = h3("选择Score2范围"), min = 0, max = 100, value = c(20,80))
        ),
        prettyCheckboxGroup("phones", h3("仅保留有效手机号?"), selected = "Yes", choices = list("Yes")),
        downloadButton("download", "下载数据")
      ),
      mainPanel(
        DTOutput("table")
      )
    )
  )
)

server <- function(input, output, session){
  # 监听确认按钮,更新第一个下拉框选项
  observeEvent(input$confirm_btn, {
    current_df <- get(input$mydata)
    updateSelectizeInput(session, "data1", "选择州", choices = c("All", unique(current_df$state)))
  })
  
  # 监听返回按钮,重置状态回到着陆页
  observeEvent(input$back_btn, {
    updateSelectizeInput(session, "data1", choices = NULL)
    updateSelectizeInput(session, "data2", choices = NULL)
    updateSelectizeInput(session, "data3", choices = NULL)
    updateActionButton(session, "confirm_btn", value = 0)
  })
  
  mydf <- reactive({get(input$mydata)})
  
  observeEvent(input$data1, {
    df <- mydf()
    updateSelectizeInput(session, "data2", "选择郡", server = TRUE, choices = c("All", unique(df$county[df$state == input$data1])))
  }, priority = 2)
  
  observeEvent(c(input$data1, input$data2), {
    df <- mydf()
    if (input$data2 != "All") {
      updateSelectizeInput(session, "data3", "选择城市", multiple = TRUE, server = TRUE, choices = c("All", unique(df$city[df$county == input$data2])))
    } else {
      updateSelectizeInput(session, "data3", "选择城市", multiple = TRUE, server = TRUE, choices = c("All", unique(df$city[df$state == input$data1])))
    }
  }, priority = 1)
  
  filtered_data <- reactive({
    temp_data <- mydf()
    if (!is.null(input$data1) && input$data1 != "All") {
      temp_data <- temp_data[temp_data$state == input$data1, ]
    }
    if (!is.null(input$data2) && input$data2 != "All") {
      temp_data <- temp_data[temp_data$county == input$data2, ]
    }
    if (!is.null(input$data3) && !"All" %in% input$data3) {
      temp_data <- temp_data[temp_data$city %in% input$data3, ]
    }
    if (input$data4 != "All") {
      temp_data <- temp_data[temp_data$demo == input$data4, ]
    }
    if (input$data5 != "All") {
      temp_data <- temp_data[temp_data$status == input$data5, ]
    }
    
    df2 <- temp_data %>% dplyr::filter(age >= input$age[1] &
                                         age <= input$age[2] &
                                         score1 >= input$score1[1] &
                                         score1 <= input$score1[2])
    if (input$mydata=="df") df2 <- df2 %>% dplyr::filter(score2 >= input$score2[1] & score2 <= input$score2[2])
    
    df3 <- if (is.null(input$phones)) df2 else df2 %>%  dplyr::filter(!is.na(phone))
    df3 %>% dplyr::select(unique_id, first_name, last_name, phone)
  })
  
  output$table <- renderDT(
    filtered_data()
  )
  
  output$download <- downloadHandler(
    filename = function() {
      paste("universe", "_", date(), ".csv", sep="")
    },
    content = function(file) {
      write.csv(filtered_data() %>% distinct_all(), file, row.names = FALSE)
    }
  )
  
}

shinyApp(ui, server)

功能说明

  • 应用启动默认显示着陆页,仅提供数据集选择入口
  • 确认数据集后自动跳转至参数配置页,选中df2时自动隐藏Score2选择滑块,筛选逻辑同步适配
  • 支持返回着陆页重新选择数据集,所有配置参数会自动重置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 03:06:04