R / Shiny로 다이나믹 한 수의 입력 요소 생성
회사에서 보험 혜택 계획을 시각화하기 위해 Shiny 앱을 작성하고 있습니다. 내가 원하는 것은 다음과 같습니다.
- 나는이있을 것이다
selectInput
또는sliderInput
사용자가 자신의 의료 보험에 개인의 수를 위치를 선택합니다 - 일치하는 수의 양면 슬라이더가 나타납니다 (각 구성원에 대해 하나씩).
- 그런 다음 플랜에있는 각 가입자의 최고 / 최악의 의료 비용에 대한 추정치를 입력 할 수 있습니다.
- 나는 그 추정치를 취하고 세 가지 계획 오퍼링에 대한 예측 비용을 보여주는 나란히 플롯을 생성하는 코드를 가지고 있으므로 추정치를 기반으로 어느 것이 가장 저렴한 지 결정할 수 있습니다.
다음 ui.R
은 하드 코딩 된 입력이있는 현재 파일이며, 4 개의 패밀리를 시뮬레이션합니다.
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
존재하지만 그 내용은 다른 UI 입력의 선택에 따라 맞게 조정됩니다),하지만 난 재봉의 예를 볼 수없는 한 수를 (또는 , 예를 들어, 유형)의 다른 UI 입력 내용의 결과로 생성되는 입력 요소입니다.
이것에 대한 제안이 있습니까 (가능합니까?)?
마지막 수단은 15 개의 입력 슬라이더를 만들어 0으로 초기화하는 것입니다. 내 코드는 잘 작동하지만 매우 큰 가족이있는 사용자를 위해 그렇게 많은 슬라이더를 만들지 않아도되므로 인터페이스를 정리하고 싶습니다.
Kevin Ushay의 답변을 기반으로 한 업데이트
나는 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()
라인을 사용할 때 3 분의 1을 얻지 못합니다 .
print(expenses)
내 expenses
함수 내부 와 같은 작업을 수행 하면 중복도 발생합니다.
# the first
mins maxs
1 NA NA
2 NA NA
# the second
mins maxs
1 0 500
2 0 500
Any tips on why my input
elements for ind1
and ind2
wouldn't show up until expenses
is called the second time and thus prevent the data frame from being created correctly?
You could handle generation of the UI element in server.R
, so you have something like:
ui.R
----
shinyUI( pageWithSideBar(
...
selectInput("numIndividuals", ...)
uiOutput("sliders"),
...
))
and
server.R
--------
shinyServer( function(input, output, session) {
output$sliders <- renderUI({
numIndividuals <- as.integer(input$numIndividuals)
lapply(1:numIndividuals, function(i) {
sliderInput(...)
})
})
})
When I have UI elements that depend on values from other UI elements, I find it easiest to generate them in server.R
.
It's useful to understand that all of the _Input
functions just generate HTML. When you want to generate that HTML dynamically it makes sense to move it to server.R
. And perhaps the other thing worth emphasizing is that it's okay to return a list
of HTML 'elements' in a renderUI
call.
다음 구문을 사용하여 shiny에서 동적으로 명명 된 변수에 액세스 할 수 있습니다.
input[["dynamically_named_element"]]
따라서 위의 예에서 슬라이더 요소를 초기화하면
# server.R
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)
})
})
# ui.R
selectInput("num", "select number of inputs", choices = seq(1,10,1))
uiOutput("input_ui")
다음을 사용하여 값을 테이블에 인쇄 할 수 있습니다.
# server.R
output$table <- renderTable({
num <- as.integer(input$num)
data.frame(lapply(1:num, function(i) {
input[[paste0("ind", i)]]
}))
})
# ui.R
tableOutput("table")
작동하는 Shiny 예제는 여기 를 참조 하십시오 . 여기서 일하는 요지 .
출처 : Joe Cheng의 첫 번째 답변, 이 스레드의 절반 정도
당신은과 사이드 바 생성 할 수 do.call
와 lapply
, 같은 뭔가를 :
# create the first input, which isn't dynamic
sel.input = 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"))
num.individuals = 5 # determine the number of individuals here
# concatenate the select input and the other inputs
inputs = c(list(sel.input), lapply(1:num.individuals, function(i) {
sliderInput(inputId = paste0("ind", i), label = paste("Individual", i), min = 0, max = 20000, value = c(0, 2500), step = 250)
}))
sidebar.panel = do.call(sidebarPanel, inputs)
참조 URL : https://stackoverflow.com/questions/19130455/create-dynamic-number-of-input-elements-with-r-shiny
'Nice programing' 카테고리의 다른 글
브라우저가 tbody 요소를 테이블 요소에 삽입하는 이유는 무엇입니까? (0) | 2020.12.25 |
---|---|
Shebang 표기 : Windows 및 Linux의 Python 스크립트? (0) | 2020.12.25 |
코드가 널 포인터를 통해 명시 적으로 정적 메서드를 호출하는 이유는 무엇입니까? (0) | 2020.12.25 |
다른 포트 뒤에있는 단일 Tomcat 인스턴스에서 다른 앱을 실행하는 방법은 무엇입니까? (0) | 2020.12.25 |
날짜 범위가있는 적절한 REST 형식 URL (0) | 2020.12.25 |