Создать динамическое количество элементов ввода с R / Shiny

Я пишу блестящее приложение для визуализации планов страховых выплат в моей компании. Вот что я хотел бы случиться:

Я буду иметьselectInput или жеsliderInput где пользователь выберет количество людей в своем медицинском планеПоявится соответствующее количество двусторонних ползунков (по одному для каждого участника)Затем они могут ввести свои оценки для наилучших / наихудших медицинских расходов для каждого участника их планаУ меня есть код, который возьмет эти оценки и создаст соседние графики, иллюстрирующие прогнозную стоимость для трех предложений плана, чтобы они могли решить, какой из них является наименее дорогим, основываясь на своих оценках

Вот мой токui.R файл с жестко закодированными входами, имитирующий семью из четырех человек:

shinyUI(pageWithSidebar(

  headerPanel("Side by side comparison"),

  sidebarPanel(

    selectInput(inputId = "class", label = "Choose plan type:",
                list("Employee only" = "emp", "Employee and spouse" = "emp_spouse",
                     "Employee and child" = "emp_child", "Employee and family" = "emp_fam")),

    sliderInput(inputId = "ind1", label = "Individual 1",
                min = 0, max = 20000, value = c(0, 2500), step = 250),

    sliderInput(inputId = "ind2", label = "Individual 2",
                min = 0, max = 20000, value = c(0, 2500), step = 250),

    sliderInput(inputId = "ind3", label = "Individual 3",
                min = 0, max = 20000, value = c(0, 2500), step = 250),

    sliderInput(inputId = "ind4", label = "Individual 4",
                min = 0, max = 20000, value = c(0, 2500), step = 250)
    ),

  mainPanel(
    tabsetPanel(  
    tabPanel("Side by Side", plotOutput(outputId = "main_plot", width = "100%")),
    tabPanel("Summary", tableOutput(outputId = "summary"))
  )
)))

Вот как это выглядит (прозрачные конечные разделы являются результатом участия HSA в двух планах. Я подумал, что это хороший способ показать как страховые взносы, так и медицинские расходы, демонстрируя влияние вклада компании HSA. Таким образом, вы просто сравнил длину сплошных цветов).

Я видел примерынравится где сам вход UI является фиксированным (в этом случае одинcheckboxGroupInput существует, но его содержимое настраивается на основе выбора из другого ввода пользовательского интерфейса), но я не видел примеров адаптацииномер (или, скажем, тип) элементов ввода, порожденных в результате содержимого другого входа пользовательского интерфейса.

Есть предложения по этому поводу (возможно ли это)?

Моим последним средством будет, скажем, создать 15 ползунков ввода и инициализировать их нулями. Мой код будет работать просто отлично, но я бы хотел очистить интерфейс, не создавая столько ползунков только для случайного пользователя, у которого очень большая семья.

Обновление на основе ответа Кевина Ушая

Я пытался пойтиserver.R маршрут и есть это:

shinyServer(function(input, output) {

  output$sliders <- renderUI({
    members <- as.integer(input$members) # default 2
    max_pred <- as.integer(input$max_pred) # default 5000
    lapply(1:members, function(i) {
      sliderInput(inputId = paste0("ind", i), label = paste("Individual", i),
                  min = 0, max = max_pred, value = c(0, 500), step = 100)
    })

  })

})

Сразу после этого я пытаюсь извлечь значения изinput для каждого человека расходы:

expenses <- reactive({
    members <- as.numeric(input$members)

    mins <- sapply(1:members, function(i) {
      as.numeric(input[[paste0("ind", i)]])[1]
    })

    maxs <- sapply(1:members, function(i) {
      as.numeric(input[[paste0("ind", i)]])[2]
    })

    expenses <- as.data.frame(cbind(mins, maxs))
})

Наконец, у меня есть две функции, которые создают объекты для хранения фрейма данных для построения графиков на основе оценок низких и высоких медицинских расходов. Они называютсяbest_case а такжеworst_case и оба нужныexpenses объект для работы, поэтому я называю это своей первой строкой, как я узнал изэтот вопрос

best_case <- reactive({

    expenses <- expenses()

    ...

)}

Я получил несколько ошибок, поэтому я использовалbrowser() пройти черезexpenses немного и заметил странные вещи, такие какinput$ind1 не кажется существующим изнутриexpenses функция.

Я также играл с различнымиprint() Заявления в нем, чтобы увидеть, что происходит. Самое поразительное, когда я делаюprint(names(input)) как самая первая строка в функции:

[1] "class"    "max_pred" "members" 

[1] "class"    "ind1"     "ind2"     "max_pred" "members" 

я получилдва выходы, которые я считаю, связано с определениемexpenses и последующий вызов этого. Странно ... Я не получаю третий, когдаworst_case использует точно такой жеexpenses <- expense() линия.

Если я сделаю что-то вродеprint(expenses) внутри моегоexpenses функция, я также получаю дубликаты:

# the first
  mins maxs
1   NA   NA
2   NA   NA

# the second
  mins maxs
1    0  500
2    0  500

Любые советы о том, почему мойinput элементы дляind1 а такжеind2 не появится доexpenses вызывается во второй раз и, таким образом, препятствует правильному созданию фрейма данных?

Ответы на вопрос(3)

Ваш ответ на вопрос