【问题标题】:Preventing Shiny selectInput from evaluating prematurely when updating a reactive plot防止 Shiny selectInput 在更新反应图时过早评估
【发布时间】:2020-08-07 15:56:16
【问题描述】:

我正在开发一个 Shiny 应用程序,它可以生成各种图表并允许用户更改图形参数。为此,我使用了selectInputnumericInputcheckboxInput 函数的组合生成图后(conditionalPanel)。我打包了代码,以便被动地计算用于图形的data.frame(以允许在绘图之前进行灵活的子集化)。一切都很好,但是当我想更新一些图形参数(例如通过selectInput 使用的颜色)时,代码会崩溃,因为它在我选择所有必要的颜色之前过早地评估(即当需要 4 种颜色时,代码选择第一种颜色后立即中断)。

我知道 debounce 延迟评估的功能,但我不想使用它,因为:

  • 我喜欢更新其他参数时图表的即时变化
  • 颜色的选择可能需要一些时间,因此很难设置预定的延迟时间/时间间隔

一种解决方案是添加有条件显示的actionButton(连同其他图形参数)来调节无功输入值的触发(见下文)。这并不理想,因为更改参数后,我需要单击更新来更新图形。另外,我不确定这将如何工作,因为km_graph 已经是一个反应性绘图对象。或者,是否有专门调节selectInput 的解决方案,以便在选择所有颜色之前不对其进行评估?

我阅读了有关此问题的几篇文章,但找不到适用于我的代码设计的解决方案。我将尝试写下我的uiserver 的部分,以了解我正在尝试做什么:

ui.R



# ...

 mainPanel(
                                  
                 plotOutput("km_graph"),
                 
                 # Conditional panel prompted only after the km_graph is generated             
                 conditionalPanel(
                     
                     condition = "output.km_graph" ,
                     
                     
                     checkboxInput("km_risk", label="Show risk table", F),
                     
                     selectInput("km_medline", label = "Mark median survival", 
                                 selected = "hv",
                                 choices = c("None" = "none",
                                             "Horizontal-Vertical" = "hv",
                                             "Vertical" = "v",
                                             "Horizontal" = "h")),
                     sliderInput("km_xlim", label="days", value = 6000, min = 10, max=10000),
                     selectInput("km_pal", "Select colors", multiple = T, 
                                 selectize = T, 
                                 selected = "jco",
                                 choices = list(`Pre-made palettes` = list("npg","aaas", "lancet", "jco", 
                                                                           "ucscgb", "UChicago", 
                                                                           "simpsons", "rickandmorty")
                                                 `Individual colors` = as.list(color_choices)) 
                                 )

# Need to find a way to prevent evaluating before all the colors are selected for km_pal

# Maybe another actionButton() here to update graph after all the parameters are selected?

服务器.R


#...
# km_results() is the reactive object containing survival analysis results
# km_dat() is the reactive data frame used in the analyses

output$km_graph <- renderPlot({
                                      

        survminer::ggsurvplot(km_results(), data = km_dat(), 
                   pval = input$km_pval,
                   pval.method = input$km_pval,
                   risk.table = input$km_risk, 
                   conf.int = input$km_confint,
                   surv.median.line = input$km_medline,
                   break.time.by = input$km_breaktime,  
                   legend="right",
                   xlim=c(0, input$km_xlim),
                   palette = input$km_pal)     ###### This breaks due to premature evaluation
              
        
    })

完整的代表

    shinyApp(
        ui = basicPage(
            
            selectInput("dat", "Select data", 
                        selected = "iris", choices = c("iris")),
            
            actionButton("go", "Go!"),

            plotOutput("plot"),
            
            conditionalPanel(
                
                h3("graphing options"),
                
                condition = "output.plot",
                
                checkboxInput("plot_point", "Show points", T),
                
                selectizeInput("plot_colors", "Select colors", selected="jco",
                               choices = list(`premade`=list("jco", "npg"),
                                              `manual`=list("red", "black", "blue")))
                
            )
            
        ),
        
        server = function(input, output) {
            
            dat <- reactive({
                
                if(input$dat == "iris") iris
                
            })
            
           output$plot <- renderPlot({
               
               req(input$go)
            
            ggpubr::ggscatter(dat(), "Sepal.Length", "Sepal.Width",
                              color="Species", palette=input$plot_colors)
                
            })
            
        }
    )
    

感谢您的见解!

【问题讨论】:

  • 请发布一个可重现的最小示例。
  • 用reprex更新了帖子。

标签: r shiny reactive


【解决方案1】:

我不确定我是否 100% 完全理解,但您可以例如将 plot_colors 输入传递到由操作按钮“应用颜色”触发的反应变量中?

(您需要在selectizeInput 的参数中添加multiple = TRUE

这是基于您的代表的代码示例:

shinyApp(
  ui = basicPage(

    selectInput("dat", "Select data", 
                selected = "iris", choices = c("iris")),

    actionButton("go", "Go!"),

    plotOutput("plot"),

    conditionalPanel(

      h3("graphing options"),

      condition = "output.plot",

      checkboxInput("plot_point", "Show points", T),

      selectizeInput("plot_colors", 
                     "Select colors", 
                     selected="jco",
                     multiple = TRUE,
                     choices = list(`premade`=list("jco", "npg"),
                                    `manual`=list("red", "black", "blue"))),

      actionButton(inputId = "apply", label = "Apply colors")

    )

  ),

  server = function(input, output) {

    dat <- reactive({

      if(input$dat == "iris") iris

    })

    params_curve <- shiny::eventReactive(eventExpr = input$apply, 
                                         {
                                           return(list(colors = input$plot_colors))
                                         },
                                         ignoreNULL = F, 
                                         ignoreInit = F
    )

    output$plot <- renderPlot({

      req(input$go)

      ggpubr::ggscatter(dat(), "Sepal.Length", "Sepal.Width",
                        color="Species", palette=params_curve()$colors)

    })



  }
)

如果您选择“红色”、“黑色”和“蓝色”,那么您的 plot_colors 变量的维度为 3。因此,绘图被渲染。

【讨论】:

  • 这似乎适用于reprex。我想我可以适应我拥有的更复杂的代码。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2020-04-05
  • 2021-06-13
  • 1970-01-01
  • 2023-03-30
  • 2020-05-05
  • 2020-06-26
  • 2017-01-17
  • 1970-01-01
相关资源
最近更新 更多