0

我正在尝试根据多个预定义列表动态生成用户输入,我的目标是通过允许它符合预定义的数据结构来简化代码的可维护性。以下是我遇到的问题的简化版本的代码和解释:

library(shiny)

distributions <- list(
  "Distribution 1" = list("Distribution 1 Parameter 1" = list("Lower" = 0, "Upper" = Inf, "Default" = 1))
)

models <- list(
  "General Model 1" = list("Specific Model 1")
)

parameters <- list(
  "Specific Model 1" = list("Specific Model 1 Parameter 1")
)

ui <- fluidPage(
  # Model selection 
  fluidRow(
    selectInput("generalModel", "General Model", names(models)),
    selectInput("specificModel", "Specific Model", models[[1]]),
    tabsetPanel(
      # Tab for inputs
      tabPanel(
        title = "Inputs",
        uiOutput("inputsTabs")
      )
    )
  )
)  

server <- function(input, output, session) {
  # Handling model selection
  observe({
    updateSelectInput(session, "specificModel", choices = models[[input$generalModel]])
  })

  # Displaying inputs for a specific model in tabs
  output$inputsTabs <- renderUI({
    nTabs = length(parameters[[input$specificModel]])
    tabs = lapply(seq_len(nTabs), function(i) {
      tabPanel(
        paste0(parameters[[input$specificModel]][[i]]),
        uiOutput(paste0(input$specificModel, "Input", parameters[[input$specificModel]][[i]]))
      )
    })
    do.call(tabsetPanel, tabs)
  })

  # Creating inputs for each specific parameter
  observe(
    lapply(seq_len(length(parameters[[input$specificModel]])), function(i) {
      output[[paste0(input$specificModel, "Input", parameters[[input$specificModel]][[i]])]] <- renderUI({
        distribution <- paste0(input$specificModel, "Input", parameters[[input$specificModel]][[i]], "Distribution")
        selectInput(inputId = distribution, label = "Distribution",  choices = names(distributions))
        uiOutput(paste0(distribution, "Parameters"))
      })
    }), 
    priority = 100
  )

  # Creating inputs for each specific parameter
  observe(
    lapply(seq_len(length(parameters[[input$specificModel]])), function(i) {
      distribution <- paste0(input$specificModel, "Input", parameters[[input$specificModel]][[i]], "Distribution")
      output[[paste0(distribution, "Parameters")]] <- renderUI({
        nNumericInputs = length(distributions[[input[[distribution]]]])
        numericInputs = lapply(seq_len(nNumericInputs), function(i) {
          numericInput(
            inputId = paste0(distribution, input[[input[[distribution]]]], distributions[[input[[distribution]]]][[i]]),
            label = paste0(distributions[[input[[distribution]]]][[i]]),
            value = distributions[[input[[distribution]]]][[i]][[3]],
            max = distributions[[input[[distribution]]]][[i]][[2]],
            min = distributions[[input[[distribution]]]][[i]][[1]]
          )
        })
        do.call(wellPanel, numericInputs)
      })
    }),
    priority = 50
  )

}

shinyApp(ui = ui, server = server)

应用程序的图像

下面描述的所有用户输入都是根据上面闪亮应用程序的 UI 之前定义的参数、模型和分布列表生成的。

因此,用户首先分别从两个下拉菜单中选择通用模型,然后选择特定模型。然后根据具体模型是什么,输入选项卡将填充与所选模型的参数对应的选项卡。然后,用户可以从选项卡内的下拉菜单中选择每个参数的分布。

之后,用户应该能够填充与分布参数相对应的一系列数字输入。我试图动态生成这些数字输入,但我不断得到:

Error: attempt to select less than one element in get1index

我尝试的代码位于应用程序的末尾并被注释掉,取消注释以重现错误。

4

0 回答 0