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

如何在Shiny中针对多变量特定分类值实现分面展示?

问题

开发用于元分析的Shiny大数据可视化应用,需实现:

  • 允许用户选择变量的特定分类值进行分面展示(而非全部值),适配后续分类值增加的场景(例如PLATFORM变量有Duobody、Hexabody、Bispecific三个取值,支持选一个或多个展示)
  • 该功能需覆盖多个变量(如PLATFORM、MUTATION)

已在UI中为PLATFORM和MUTATION设置conditionalPanel,选择对应变量作为行分面时弹出选择框,但server端facet_grid/facet_wrap仍显示该变量的所有分类值,无法实现筛选效果。

解决方案

核心思路是先基于用户选择过滤数据,再用过滤后的数据绘图分面,具体步骤:

1. 修复UI中的错误

  • 修正conditionalPanel的拼写错误:conditoin改为condition
  • 在row选择框的选项中添加"Mutation"(原代码中row选项无此值,导致对应的conditionalPanel无法触发)

2. 构建反应式过滤数据

在server中创建反应式数据集,根据用户选择的行分面变量(input$row)和对应的分类选择(如input$platform、input$mutation)过滤原始数据df。

3. 使用过滤后的数据绘图

用反应式数据替代原始数据绘图,分面时用更规范的语法构建公式,确保只展示用户选定的分类值。

修改后的完整代码

UI代码

ui <- fluidPage(
    
    tabsetPanel(tabPanel("Tab 1",
                         
        titlePanel("Shiny App: Concentration vs Time Graphs"),
                         
         sidebarLayout(
            mainPanel("Concentration vs Time graphs", plotOutput(outputId = "plot")),
            sidebarPanel(helpText("This app is developed to visualize pharmacokinetic data of different antibodies..."),
            selectInput(
                inputId = "study",
                label = "Include study:",
                choices = c("GLP Toxicity" = "ME1044-011", "Dose Range Finding", "Single Dose", "Repeat Dose"),
                selected = "ME1044-011",
                multiple = T
            ),
            selectInput(
                inputId = "x",
                label = "X-axis:",
                choices = c("Time" = "TIME", "TLD"),
                selected = "Time"
            ),
            selectInput(
                inputId = 'column',
                label = "Columns for:",
                choices = c("Dose mg/kg" = "DOSEMGKG", "Species" = "SPECIES", "Antibody" = "ABXID", "Subspecies" = "SUBSPECIES", "Age" = "AGE", "Animal ID" = "ANIMALID"),
                selected = "DOSEMGKG"
            ),
            selectInput(
                inputId = 'row',
                label = "Rows for:",
                choices = c("Dose mg/kg" = "DOSEMGKG", "Species" = "SPECIES", "Antibody" = "ABXID", "Subspecies" = "SUBSPECIES", "Age" = "AGE",  "Animal ID" = "ANIMALID", "Platform" = "PLATFORM", "Mutation" = "MUTATION"),
                selected = "ABXID"
            ),
            conditionalPanel(
                condition = "input.row == 'PLATFORM'",
                selectInput(
                    inputId = 'platform',
                    label = "Choose platform(s)",
                    choices = c("Hexabody", "Duobody", "Bispecific"), multiple = T,
                    selected = c("Hexabody") # 默认选一个值,避免空选择报错
                 )
            ),
            conditionalPanel(
                condition = "input.row == 'MUTATION'",
                selectInput(
                    inputId = 'mutation',
                    label = "Choose mutation(s):",
                    choices = c('M1', "M2", "M3"), multiple = T,
                    selected = c("M1") # 默认选一个值,避免空选择报错
                )
            ),
            selectInput(
                inputId = "group",
                label = "Group by:",
                choices = c("Dose mg/kg" = "DOSEMGKG", "Species" = "SPECIES", "Antibody" = "ABXID", "Subspecies" = "SUBSPECIES", "Age" = "AGE",  "Animal ID" = "ANIMALID"),
                selected = "ANIMALID"
            ),
            sliderInput(
                inputId = 'trange',
                label = "Time range:",
                min = 0,
                max = 1704,
                value = c(0, 1704 )
            )
                    ))
                         
    )),
    
    
    tabsetPanel(tabPanel("Tab 2",
                         
        titlePanel("Tab 2"),
                         
            sidebarLayout(
                mainPanel("Plot #2", plotOutput(outputId = "plot2")),
                    sidebarPanel(helpText("Whatever text..."),
                        selectInput(
                        inputId = 't',
                        label = "Example",
                        choices = c("#1", "#2", "#3"),
                        selected = "#1"
                        )
                             )
                         )))
)

Server代码

server <- function(input, output, session){
    
    # 构建反应式过滤数据
    filtered_df <- reactive({
        temp_df <- df
        
        # 根据行分面变量过滤分类值
        if(input$row == "PLATFORM"){
            temp_df <- temp_df[temp_df$PLATFORM %in% input$platform, ]
        } else if(input$row == "MUTATION"){
            temp_df <- temp_df[temp_df$MUTATION %in% input$mutation, ]
        }
        
        # 时间范围过滤
        temp_df <- temp_df[temp_df[[input$x]] >= input$trange[1] & temp_df[[input$x]] <= input$trange[2], ]
        
        # 研究筛选(原UI有该选项但未使用)
        if(!is.null(input$study)){
            temp_df <- temp_df[temp_df$STUDY %in% input$study, ]
        }
        
        temp_df
    })
    
    output$plot <- renderPlot({
        ggplot(data = filtered_df(), aes_string(x = input$x, y = "DV", col = input$group)) + 
            xlab("Time") + 
            ylab("Concentration (ug/mL)") +
            geom_point() + 
            facet_grid(reformulate(input$column, input$row)) + # 用reformulate替代get(),语法更规范
            scale_x_continuous(limits = input$trange) + 
            scale_color_viridis(discrete = T) + 
            theme_bw() 
    })
    
}

shinyApp(ui = ui, server = server)
关键说明
  • 反应式数据filtered_df()会实时根据用户选择过滤原始数据,确保绘图只包含选定的分类值
  • 使用reformulate()构建分面公式,比get()更符合ggplot语法规范,避免潜在问题
  • 给分类选择框设置默认值,防止用户未选择时出现空数据报错
  • 补上了原UI中study选项的过滤逻辑(之前代码未使用该输入)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:25:24