Shiny下拉框筛选含2个冒号的交互项时失效问题排查
Shiny下拉框显示异常问题排查与解决
问题描述
在大型Shiny应用中,基于ANOVA输出创建绘图用下拉框,通过行名中的冒号数量区分交互项:1个冒号对应双向交互,2个冒号对应三向交互。当筛选双向交互或所有交互项时,下拉框工作正常;但筛选三向交互(将模式匹配条件改为>1或==2)时,下拉框显示choices对应的dataframe名称而非选项本身,虽能返回选中值但显示异常。
错误原因
selectInput的choices参数接受向量或命名列表:
- 当传入的dataframe包含多行数据时,Shiny会自动提取列值作为选项,显示正常;
- 当dataframe仅包含一行数据时,Shiny会将其解析为以列名为键、行值为值的命名列表,导致下拉框显示列名而非实际交互项。
解决方法
直接传入字符向量而非dataframe给choices参数,有两种实现方式:
方式1:直接生成筛选后的字符向量(推荐)
去掉不必要的dataframe转换,直接筛选行名生成向量:
# 替换原代码中int_sel相关的行 int_sel <- rownames(head(aov_l,-1)) %>% keep(~str_count(.x, pattern = ":") > 1) # 筛选三向交互(冒号数>1)
方式2:从dataframe中提取列向量
如果保留dataframe处理流程,需提取对应列的向量传入choices:
# 原int_sel处理不变,修改selectInput的choices参数 selectInput(inputId = "ems_int_selected", label = int_title, choices = int_sel$Interactions, # 提取列向量 multiple = TRUE, width = "100%" )
修正后的完整代码
library(shiny) library(dplyr) library(stringr) # 需加载stringr包,原代码用到str_count但未显式加载 # Define UI ui <- fluidPage( uiOutput("ems_int_sel"), textOutput("selection") ) # Define server logic server <- function(input, output) { output$ems_int_sel<-renderUI({ aov_l<-structure(list(Df = c(1, 1, 1, 1, 1, 1, 1, 72), SS = c(0.199999999999973,0.112500000000021, 2.4500000000001, 25.3124999999997, 4.99999999999986,0.11249999999998, 1.07995057924757e-27, 13.9999999999996), MS = c(0.199999999999973,0.112500000000021, 2.4500000000001, 25.3124999999997, 4.99999999999986,0.11249999999998, 1.07995057924757e-27, 0.194444444444439), Fvalue = c("1.0286","0.5786", "12.6", "130.1786", "25.7143", "0.5786", "0", ""), Pvalue = c("0.3139", "0.4494", "7e-04", "<0.0001", "<0.0001","0.4494", "1", ""), Sig = c("", "", "***", "***", "***","", "", ""), EMS = c("Error+40atm", "Error+40rzt", "Error+20atm:rzt","Error+40salt", "Error+20atm:salt", "Error+20rzt:salt", "Error+10atm:rzt:salt","Error")), class = "data.frame", row.names = c("atm", "rzt","atm:rzt", "salt", "atm:salt", "rzt:salt", "atm:rzt:salt", "Residuals")) req(aov_l) # 直接生成筛选后的字符向量 int_sel <- rownames(head(aov_l,-1)) %>% keep(~str_count(.x, pattern = ":") > 1) disp<-TRUE int_title<-if(disp){ "Show Three-Way Interaction Plots for Dispersion:" } else { "Show Three-Way Interaction Plots for Means:" } selectInput(inputId = "ems_int_selected", label = int_title, choices = int_sel, multiple = TRUE, width = "100%" ) }) output$selection<-renderText({ input$ems_int_selected }) } # Run the application shinyApp(ui = ui, server = server)
内容的提问来源于stack exchange,提问作者Steven Ouellette
相关产品推荐
相关产品推荐

