如何在 Shiny 中创建相互依赖的数字输入?
How to create mutually dependent numeric Input in Shiny?
请在下面找到工作代码。
基本上,有 3 个 numericInputs 允许用户一次更改任何人,另外 2 个应自行调整,结果为 1
A + B + C = 1
但是,由于它们是相通的,它们似乎不稳定。
我们如何才能使其稳定并允许用户更改任何 1 个变量:A 和其他 2 个更改自己总和为 1。
根据此处的答案,创建了如下所示的工作代码:
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Mutually Dependent Input Values"),
sidebarLayout(
sidebarPanel(
numericInput("A", "A",.333),
numericInput("B", "B",.333),
numericInput("C", "C",.333)
),
mainPanel(
verbatimTextOutput("result")
)
)
))
server <- shinyServer(function(input, output,session) {
observeEvent(input$A,{
newB <- 1 - input$A - input$C
updateNumericInput(session, "B", value = newB)
newC <- 1 - input$A - input$B
updateNumericInput(session, "C", value = newC)
})
observeEvent(input$B,{
newC <- 1 - input$B - input$A
updateNumericInput(session, "C", value = newC)
newA <- 1 - input$B - input$C
updateNumericInput(session, "A", value = newA)
})
observeEvent(input$C,{
newA <- 1 - input$C - input$B
updateNumericInput(session, "A", value = newA)
newB <- 1 - input$C - input$C
updateNumericInput(session, "B", value = newB)
})
})
shinyApp(ui,server)
基本上,用户可以自由更新任何一个numericInput:A、B或C。其他2个numericInput应该自行调整以求和为1。
目前由于是相通的,所以好像不稳定(请找上面的代码重新生成错误)
####### 不同的方法和自己的解决方案
ui <- fluidPage(
column(6,
tags$h2("Set parameters"),
numericInput("valueA", "Value1", value = .333, min = 0, max = 1, step = .1),
numericInput("valueB", "Value2", value = .333, min = 0, max = 1, step = .1),
numericInput("valueC", "Value3", value = .333, min = 0, max = 1, step = .1)
),
column(6,
uiOutput("ui")
)
)
server <- function(input, output, session) {
output$ui <- renderUI( {
tagList(
tags$h2("Display in %"),
numericInput("obs1", "Label1", value = 100 * (input$valueA / (input$valueA + input$valueB + input$valueC))),
numericInput("obs2", "Label2", value = 100 * (input$valueB / (input$valueA + input$valueB + input$valueC))),
numericInput("obs2", "Label2", value = 100 * (input$valueC / (input$valueA + input$valueB + input$valueC)))
)
})
}
shinyApp(ui, server)
你需要做两件主要的事情:
首先让你的初始值稳定,所以它们的总和应该是1(0.333,0.333,0.334),或者让初始值为空,只有当你有某种类型的错误转义机制允许 NA 或空字符串作为初始值时,它才会起作用。正如我认为在任何情况下都应该对输入是数字进行一些验证一样,我选择使用第二个选项,它与验证配合得很好。
第二种摆脱观察和更改输入的无限循环的方法是一次更改一个,意思是:
- 如果更改 A ---> 更改 B,
- 如果 B 改变了 ---> 改变 C,并且
- 如果更改 C ---> 更改 A
话虽这么说,但请注意,更改输入的顺序在此方法中有所不同,这在开始时为输入提供第一组值时最为明显。
可能有更好的方法来解决这个问题,但这是我能想到的,所以就这样吧。
UI:
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Mutually Dependent Input Values"),
sidebarLayout(
sidebarPanel(
numericInput("A", "A", NA),
numericInput("B", "B", NA),
numericInput("C", "C", NA)
),
mainPanel(
verbatimTextOutput("result")
)
)
))
服务器:
server <- shinyServer(function(input, output, session) {
sum <- reactive({
validate(
need(is.numeric(input$A), 'A is not a number, only numbers are allowed'),
need(is.numeric(input$B), 'B is not a number, only numbers are allowed'),
need(is.numeric(input$C), 'C is not a number, only numbers are allowed')
)
input$A + input$B + input$C})
observeEvent(input$A,{
newB <- 1 - input$A - input$C
updateNumericInput(session, "B", value = newB)
})
observeEvent(input$B,{
newC <- 1 - input$B - input$A
updateNumericInput(session, "C", value = newC)
})
observeEvent(input$C,{
newA <- 1 - input$C - input$B
updateNumericInput(session, "A", value = newA)
})
output$result <- renderPrint({
print(sprintf("A=%.3f B=%.3f C=%.3f ----> A + B + C = %.0f",
input$A, input$B, input$C, sum()))
})
})
运行:
shinyApp(ui,server)
请在下面找到工作代码。 基本上,有 3 个 numericInputs 允许用户一次更改任何人,另外 2 个应自行调整,结果为 1
A + B + C = 1 但是,由于它们是相通的,它们似乎不稳定。 我们如何才能使其稳定并允许用户更改任何 1 个变量:A 和其他 2 个更改自己总和为 1。
根据此处的答案,创建了如下所示的工作代码:
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Mutually Dependent Input Values"),
sidebarLayout(
sidebarPanel(
numericInput("A", "A",.333),
numericInput("B", "B",.333),
numericInput("C", "C",.333)
),
mainPanel(
verbatimTextOutput("result")
)
)
))
server <- shinyServer(function(input, output,session) {
observeEvent(input$A,{
newB <- 1 - input$A - input$C
updateNumericInput(session, "B", value = newB)
newC <- 1 - input$A - input$B
updateNumericInput(session, "C", value = newC)
})
observeEvent(input$B,{
newC <- 1 - input$B - input$A
updateNumericInput(session, "C", value = newC)
newA <- 1 - input$B - input$C
updateNumericInput(session, "A", value = newA)
})
observeEvent(input$C,{
newA <- 1 - input$C - input$B
updateNumericInput(session, "A", value = newA)
newB <- 1 - input$C - input$C
updateNumericInput(session, "B", value = newB)
})
})
shinyApp(ui,server)
基本上,用户可以自由更新任何一个numericInput:A、B或C。其他2个numericInput应该自行调整以求和为1。 目前由于是相通的,所以好像不稳定(请找上面的代码重新生成错误)
####### 不同的方法和自己的解决方案
ui <- fluidPage(
column(6,
tags$h2("Set parameters"),
numericInput("valueA", "Value1", value = .333, min = 0, max = 1, step = .1),
numericInput("valueB", "Value2", value = .333, min = 0, max = 1, step = .1),
numericInput("valueC", "Value3", value = .333, min = 0, max = 1, step = .1)
),
column(6,
uiOutput("ui")
)
)
server <- function(input, output, session) {
output$ui <- renderUI( {
tagList(
tags$h2("Display in %"),
numericInput("obs1", "Label1", value = 100 * (input$valueA / (input$valueA + input$valueB + input$valueC))),
numericInput("obs2", "Label2", value = 100 * (input$valueB / (input$valueA + input$valueB + input$valueC))),
numericInput("obs2", "Label2", value = 100 * (input$valueC / (input$valueA + input$valueB + input$valueC)))
)
})
}
shinyApp(ui, server)
你需要做两件主要的事情:
首先让你的初始值稳定,所以它们的总和应该是1(0.333,0.333,0.334),或者让初始值为空,只有当你有某种类型的错误转义机制允许 NA 或空字符串作为初始值时,它才会起作用。正如我认为在任何情况下都应该对输入是数字进行一些验证一样,我选择使用第二个选项,它与验证配合得很好。
第二种摆脱观察和更改输入的无限循环的方法是一次更改一个,意思是:
- 如果更改 A ---> 更改 B,
- 如果 B 改变了 ---> 改变 C,并且
- 如果更改 C ---> 更改 A
话虽这么说,但请注意,更改输入的顺序在此方法中有所不同,这在开始时为输入提供第一组值时最为明显。
可能有更好的方法来解决这个问题,但这是我能想到的,所以就这样吧。
UI:
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Mutually Dependent Input Values"),
sidebarLayout(
sidebarPanel(
numericInput("A", "A", NA),
numericInput("B", "B", NA),
numericInput("C", "C", NA)
),
mainPanel(
verbatimTextOutput("result")
)
)
))
服务器:
server <- shinyServer(function(input, output, session) {
sum <- reactive({
validate(
need(is.numeric(input$A), 'A is not a number, only numbers are allowed'),
need(is.numeric(input$B), 'B is not a number, only numbers are allowed'),
need(is.numeric(input$C), 'C is not a number, only numbers are allowed')
)
input$A + input$B + input$C})
observeEvent(input$A,{
newB <- 1 - input$A - input$C
updateNumericInput(session, "B", value = newB)
})
observeEvent(input$B,{
newC <- 1 - input$B - input$A
updateNumericInput(session, "C", value = newC)
})
observeEvent(input$C,{
newA <- 1 - input$C - input$B
updateNumericInput(session, "A", value = newA)
})
output$result <- renderPrint({
print(sprintf("A=%.3f B=%.3f C=%.3f ----> A + B + C = %.0f",
input$A, input$B, input$C, sum()))
})
})
运行:
shinyApp(ui,server)