Crie um número dinâmico de elementos de entrada com R / Shiny
Estou escrevendo um aplicativo brilhante para visualizar planos de benefícios de seguro na minha empresa. Aqui está o que eu gostaria de acontecer:
Eu vou ter umselectInput
ousliderInput
onde o usuário escolherá o número de pessoas em seu plano médicoUm número correspondente de controles deslizantes de dois lados aparecerá (um para cada membro)Eles podem então inserir suas estimativas para as melhores e piores despesas médicas para cada membro em seu plano.Eu tenho um código que pegará essas estimativas e criará gráficos lado a lado, ilustrando o custo previsto nas três ofertas de planos, para que eles possam decidir qual é o menos caro, com base em suas estimativas.Aqui está o meu atualui.R
arquivo com entradas codificadas, simulando uma família de quatro:
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"))
)
)))
Aqui está o que parece (as seções finais transparentes são o resultado de contribuições de HSA de dois dos planos. Eu pensei que era uma maneira agradável de mostrar os prêmios e despesas médicas, mostrando o impacto da contribuição da empresa HSA. Assim, você Basta comparar o comprimento das cores sólidas).
Eu vi exemploscomo isso onde a própria entrada da interface do usuário é fixa (neste caso,checkboxGroupInput
existe, mas o seu conteúdo é adaptado com base na escolha de outra entrada da interface do usuário), mas eu não vi exemplos de alfaiatariao número (ou, digamos, digite) dos elementos de entrada gerados como resultado do conteúdo de outra entrada da interface do usuário.
Alguma sugestão sobre isso (é mesmo possível)?
Meu último recurso será criar, digamos, 15 controles deslizantes de entrada e inicializá-los para zero. Meu código funcionará muito bem, mas eu gostaria de limpar a interface por não ter que criar muitos sliders apenas para o usuário ocasional que tem uma família muito grande.
Atualização com base na resposta de Kevin Ushay
Eu tentei ir noserver.R
rota e tem isso:
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)
})
})
})
Imediatamente depois, eu tento extrair os valores deinput
para as despesas de cada indivíduo:
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))
})
Por fim, tenho duas funções que criam objetos para armazenar um quadro de dados para plotagem com base nas estimativas de despesas médicas baixas e altas. Eles são chamadosbest_case
eworst_case
e ambos precisam doexpenses
Objeto para o trabalho, então eu chamo-o como minha primeira linha como eu aprendi comessa questão
best_case <- reactive({
expenses <- expenses()
...
)}
Eu tenho alguns erros, então eu useibrowser()
percorrer oexpenses
pouco e notei coisas peculiares comoinput$ind1
não parece existir dentro doexpenses
função.
Eu também brinquei com váriosprint()
declarações nele para ver o que estava acontecendo. O mais impressionante é quando eu façoprint(names(input))
como a primeira linha na função:
[1] "class" "max_pred" "members"
[1] "class" "ind1" "ind2" "max_pred" "members"
eu recebodois saídas, o que eu acredito é devido à definição deexpenses
e subseqüente chamado dele. Estranhamente ... eu não tenho um terceiro quandoworst_case
usa exatamente o mesmoexpenses <- expense()
linha.
Se eu fizer algo comoprint(expenses)
dentro do meuexpenses
função, eu também recebo duplicatas:
# the first
mins maxs
1 NA NA
2 NA NA
# the second
mins maxs
1 0 500
2 0 500
Alguma dica sobre o porquê do meuinput
elementos paraind1
eind2
não apareceria atéexpenses
é chamado a segunda vez e assim impedir que o quadro de dados seja criado corretamente?