闪亮:如何将 renderUI() 中的 sliderInput 的值集成到 renderPlot() 中使用的 eventReactive()

shiny: How to integrate values from sliderInput within renderUI() into an eventReactive() used in renderPlot()

我的 app 打印一个 renderUI() 包含一个 tabsetPanel() 包含一个基于 sliderInput() input$n_fjernet 来自 ui[=32] 的图=]

问题

想法是,renderUI() returns (1) 一个名为 input$time_cali 的新 sliderInput() 反应式插入在 plotCalibration 中的 ( ...) times=reactive({input$time_cali}), 参数中选择滑块值,目前已写入 60;和 (2)output$cali_plot 应该 print/update 根据存储在 [=27= 中的 renderUI()input$time_cali 值进行反应]

如何做到这一点?

预期输出

我尝试了 times=reactive({input$time_cali})eventReactive()

的各种变体

写成

library(shiny)
library(shinyjs)
library(survival)
library(tidyverse)
library(riskRegression)
library(rms)

ui <- fluidPage(


  useShinyjs(),

  fluidRow(

    column(
      12,
      wellPanel(
        style = "height:150px", 
        sliderInput("n_fjernet", "Lymph Nodal Yield", 
                    min = 4, max = 120, value = 40)
      )
    ),

    fluidRow(align="center", br(), actionButton("do", "Submit"),

             fluidRow(br(),

                      column(12, 

                             uiOutput("test")
                      )
             )
    )
  )
)

server <- function(input, output, session) {

  fit_data <- eventReactive(input$do, {
    p %>% filter(n_fjernet == as.numeric(input$n_fjernet))
  })


  reactive_cali_plot <- eventReactive(input$do, {

    plotCalibration(Score(list(Nomogram=cph(Surv(os.neck,mors)~alder,
                                            data=fit_data(), y=TRUE, x=TRUE)), 
                          Hist(os.neck,mors)~1,
                          data=fit_data(), 
                          plots=c("cal"),
                          times=60, ## This part should be reactively based on input$time_cali from renderUI() in output$test
                          metrics=c("auc","brier")), 
                    cens.method = "local", 
                    legend.x=.6,
                    legend.y=.35,
                    cex=1,
                    brier.in.legend = TRUE,
                    auc.in.legend = TRUE)
  })

  output$cali_plot <- renderPlot({


    reactive_cali_plot()

  })


  observeEvent(input$do, {

    output$test <- renderUI({


      tabsetPanel(id = "something", 
                  tabPanel(title = "Cali plot",
                           sliderInput("time_cali", "Months to predict", 
                                       min = 12, max = 120, value = 60),
                           plotOutput("cali_plot",width = "90%", height="650px"))

      )
    })
  })


}

shinyApp(ui, server)

我的数据p

p <- structure(list(os.neck = c(9.63, 7.03, 9.17, 10.48, 7.69, 15.18, 
13.5, 16.33, 15.31, 12.09, 12.35, 22.28, 15.77, 14.39, 10.02, 
14.52, 8.44, 23.82, 5.95, 3.78, 19.32, 20.14, 15.51, 19.78, 12.98, 
32.92, 9.76, 5.65, 30.75, 2.79, 33.58, 27.53, 27.63, 14.62, 29.17, 
25.4, 18.43, 5.29, 30.75, 28.48, 14.69, 13.14, 6.6, 26.81, 40.74, 
11.63, 13.31, 10.41, 9.56, 17.51, 35.78, 35.75, 37.62, 33.25, 
36.96, 34.56, 40.05, 41.26, 24.34, 37.49, 40.94, 24.11, 39.33, 
11.24, 39.1, 19.75, 38.93, 39.36, 36.34, 48, 29.17, 47.93, 3.68, 
24.21, 46.36, 49.12, 50.96, 14.16, 54.01, 19.88, 50.86, 1.87, 
54.24, 13.93, 11.6, 10.05, 23.1, 62.78, 12.58, 39, 59.83, 6.77, 
60.39, 18.46, 61.77, 58.41, 49.45, 64.26, 2.4, 26.51, 58.94, 
69.91, 64.66, 55.56, 46.55, 29.63, 55.66, 19.68, 7.62, 2.73, 
17.77, 10.12, 9.95, 74.22, 57.3, 58.94, 27.01, 34.23, 78.82, 
27.2, 83.02, 76.68, 58.15, 22.18, 14.49, 3.91, 25.92, 74.64, 
66.83, 70.74, 38.08, 7.69, 74.55, 49.94, 11.1, 88.54, 6.44, 79.54, 
80.82, 70.83, 12.91, 81.25, 17.38, 29.96, 94.72, 73.53, 72.54, 
1.35, 89.69, 62.85, 7.62, 93.27, 5.09, 51.25, 62, 55.33, 44.62, 
56.94, 94.55, 88.61, 32.46, 11.04, 16.53, 100.04, 24.74, 24.54, 
5.75, 59.83, 59.83, 77.77, 92.78, 49.58, 91.2, 1.18, 18.92, 6.34, 
32.46, 72.41, 105.82, 1.84, 12.78, 57.56, 59.14, 104.08, 15.54, 
117.75, 4.27, 67.61, 19.78, 112.49, 53.59, 107.01, 47.57, 9.46, 
53.59, 46.46, 57.33, 18.76, 82.04, 13.67, 67.45, 28.98, 21.19, 
121.4, 91.07, 50.83, 121.72, 123.04, 6.31, 123.5, 58.68, 9.56, 
34.1, 90.48, 71.1, 11.33, 65.35, 54.21, 34.99, 62.06, 199.1, 
65.74, 61.64, 15.44, 52.21, 19.88, 7.82, 5.39, 39.98, 5.49, 35.98, 
22.67, 26.55, 23.89, 22.44, 1.77, 14.92, 17.64, 11.53, 58.74, 
0.82, 0.26, 25.17, 18.27, 18.46, 9.17, 18.27, 129.71, 153.7, 
123.86), mors = c(0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 1L, 0L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 
1L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 
0L, 0L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 
0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L, 1L, 0L, 1L, 1L, 0L, 
1L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
1L, 1L, 0L, 1L, 1L, 1L, 0L, 1L, 0L, 1L, 1L, 0L, 1L, 0L, 0L, 1L, 
1L, 1L, 1L, 1L, 0L, 0L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 
0L, 1L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 1L, 0L, 
1L, 1L, 0L, 0L, 0L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 
1L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 
1L, 1L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L, 
0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 1L, 0L, 
1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L), 
    n_fjernet = c(22L, 61L, 50L, 47L, 30L, 60L, 82L, 60L, 33L, 
    67L, 35L, 56L, 15L, 37L, 44L, 124L, 41L, 30L, 31L, 35L, 36L, 
    28L, 39L, 54L, 25L, 27L, 69L, 53L, 24L, 33L, 52L, 77L, 51L, 
    7L, 22L, 53L, 26L, 58L, 28L, 83L, 39L, 15L, 37L, 27L, 9L, 
    17L, 32L, 26L, 44L, 52L, 22L, 62L, 53L, 68L, 52L, 38L, 50L, 
    21L, 41L, 74L, 15L, 26L, 36L, 37L, 34L, 22L, 31L, 53L, 13L, 
    44L, 43L, 51L, 20L, 21L, 63L, 40L, 25L, 17L, 43L, 47L, 35L, 
    21L, 4L, 23L, 35L, 50L, 69L, 24L, 38L, 45L, 37L, 35L, 25L, 
    19L, 43L, 19L, 33L, 38L, 50L, 21L, 40L, 100L, 45L, 53L, 41L, 
    7L, 75L, 48L, 20L, 11L, 72L, 37L, 34L, 70L, 20L, 47L, 44L, 
    45L, 48L, 23L, 27L, 24L, 39L, 9L, 34L, 22L, 89L, 40L, 35L, 
    34L, 61L, 28L, 27L, 62L, 47L, 13L, 20L, 9L, 27L, 38L, 44L, 
    15L, 33L, 65L, 31L, 49L, 53L, 15L, 26L, 17L, 24L, 20L, 25L, 
    12L, 34L, 22L, 27L, 14L, 27L, 31L, 26L, 15L, 16L, 30L, 19L, 
    51L, 12L, 33L, 68L, 26L, 20L, 34L, 31L, 7L, 76L, 7L, 24L, 
    36L, 22L, 27L, 35L, 64L, 18L, 38L, 10L, 27L, 26L, 47L, 15L, 
    30L, 30L, 21L, 31L, 14L, 14L, 22L, 28L, 13L, 17L, 16L, 7L, 
    11L, 37L, 55L, 13L, 26L, 17L, 12L, 44L, 58L, 20L, 28L, 7L, 
    24L, 10L, 42L, 39L, 14L, 31L, 49L, 87L, 18L, 26L, 24L, 20L, 
    41L, 31L, 13L, 41L, 25L, 16L, 18L, 26L, 35L, 36L, 22L, 20L, 
    16L, 10L, 19L, 46L, 6L, 49L, 70L, 46L, 55L, 25L, 22L, 37L, 
    28L), alder = c(47, 50, 61, 83, 38, 44, 45, 47, 52, 54, 56, 
    58, 58, 59, 63, 65, 65, 67, 71, 71, 73, 73, 77, 88, 89, 35, 
    35, 41, 47, 48, 49, 51, 51, 53, 55, 59, 60, 65, 67, 68, 68, 
    70, 74, 84, 27, 48, 49, 50, 55, 56, 57, 58, 58, 60, 62, 62, 
    63, 63, 64, 64, 66, 70, 71, 72, 75, 76, 80, 83, 84, 44, 46, 
    51, 58, 59, 60, 61, 63, 63, 66, 66, 67, 69, 70, 79, 80, 82, 
    84, 51, 53, 53, 54, 54, 54, 57, 58, 59, 60, 61, 61, 62, 62, 
    67, 71, 72, 72, 73, 75, 77, 80, 85, 38, 46, 49, 49, 51, 52, 
    54, 54, 55, 55, 58, 59, 61, 62, 63, 64, 66, 66, 66, 67, 70, 
    71, 73, 73, 81, 34, 41, 46, 47, 51, 54, 54, 55, 57, 57, 58, 
    58, 60, 61, 64, 75, 77, 78, 79, 80, 83, 86, 36, 38, 42, 47, 
    49, 49, 49, 52, 53, 55, 55, 55, 60, 62, 63, 63, 64, 64, 65, 
    67, 67, 68, 69, 71, 71, 80, 80, 38, 39, 47, 51, 53, 53, 58, 
    58, 66, 67, 69, 70, 73, 74, 76, 87, 43, 46, 53, 55, 56, 56, 
    59, 60, 61, 68, 70, 74, 77, 80, 51, 63, 70, 52, 56, 75, 65, 
    65, 41, 82, 47, 56, 66, 65, 49, 75, 48, 72, 43, 52, 77, 51, 
    57, 53, 64, 50, 86, 69, 72, 39, 65, 63, 27, 75, 49, 61)), row.names = c(NA, 
250L), class = "data.frame")

描述的预期行为有点令人困惑,但这里有一些可能有用的想法:

  • 我会避免将 output 嵌入到 observeEvent
  • 您的 fit_data 可能只是一个 reactive 表达式
  • plotCalibration方法可以只用input$time_cali
  • 您可以使用简单的 observeEvent 检测按钮何时按下,然后显示隐藏的 sliderInputplotOutput 小部件

这是否更接近您的需求?

library(shiny)
library(shinyjs)
library(survival)
library(tidyverse)
library(riskRegression)
library(rms)

ui <- fluidPage(
  useShinyjs(),
  fluidRow(
    column(
      12,
      wellPanel(
        style = "height:150px", 
        sliderInput("n_fjernet", "Lymph Nodal Yield", 
                    min = 4, max = 120, value = 40)
      )
    ),
    fluidRow(align="center", br(), actionButton("do", "Submit"),
             fluidRow(br(),
                      column(12, 
                             hidden(tags$div(
                               id = "hidden_items",
                               tabsetPanel(id = "something", 
                                           tabPanel(title = "Cali plot",
                                                    sliderInput("time_cali", "Months to predict", 
                                                                min = 12, max = 120, value = 60),
                                                    plotOutput("cali_plot",width = "90%", height="650px"))
                               )
                             ))
                      )
             )
    )
  )
)

server <- function(input, output, session) {

  fit_data <- reactive({
    p %>% filter(n_fjernet == as.numeric(input$n_fjernet))
  })

  observeEvent(input$do, {
    show("hidden_items")
  })

  reactive_cali_plot <- reactive({
    plotCalibration(Score(list(Nomogram=cph(Surv(os.neck,mors)~alder,
                                            data=fit_data(), y=TRUE, x=TRUE)),
                          Hist(os.neck,mors)~1,
                          data=fit_data(),
                          plots=c("cal"),
                          times=input$time_cali, ## This part should be reactively based on input$time_cali from renderUI() in output$test
                          metrics=c("auc","brier")),
                    cens.method = "local",
                    legend.x=.6,
                    legend.y=.35,
                    cex=1,
                    brier.in.legend = TRUE,
                    auc.in.legend = TRUE)
  })

  output$cali_plot <- renderPlot({
    reactive_cali_plot()
  })

}

shinyApp(ui, server)