在以下示例中,计算numberInput
“数字C”并将其更新为“数字A”除以“数字B”。当结果是一个无穷小数时,这将导致一个数字很多,并且到“数字C”。我想将无限制的小数点四舍五入到第二或第三位数字,以使外观更易于阅读“数字C”。但是,与此同时,我不想将round
函数应用于num_C
,因为在现实世界中,我想将“数字C”应用于其他计算,并且希望使用该数字照原样。换句话说,我想找到一种格式化数字的外观而不格式化其实际价值的方法,例如格式化Excel电子表格中的单元格以仅显示有限的数字而不更改其实际价值。这可以在Shiny中完成吗?
library(shiny)
# Define UI
ui <- fluidPage(
numericInput(inputId = "A", "Number A", value = 2),
numericInput(inputId = "B", "Number B", value = 3),
numericInput(inputId = "C", "Number C [A/B]", value = 1)
)
# Server logic
server <- function(input, output, session){
observe({
req(input$A, input$B)
num_C <- input$A/input$B
updateNumericInput(
inputId = "C",
session = session,
value = num_C
)
})
}
# Complete app with UI and server components
shinyApp(ui, server)
答案 0 :(得分:4)
您可以对reactive
使用num_C
表达式
library(shiny)
# Define UI
ui <- fluidPage(
numericInput(inputId = "A", "Number A", value = 2),
numericInput(inputId = "B", "Number B", value = 3),
numericInput(inputId = "C", "Number C [A/B]", value = 1)
)
# Server logic
server <- function(input, output, session){
num_C <- reactive({
req(input$A, input$B)
input$A / input$B
})
observe(
updateNumericInput(
inputId = "C",
session = session,
value = format(num_C(), digits = 2))
)
}
# Complete app with UI and server components
shinyApp(ui, server)
num_C()
将返回“未取整”值,而我们在format(num_C(), digits = 2)
中使用取整值updateNumericInput
。
关于它的价值,这是一个不完整的更新
library(shiny)
# Define UI
ui <- fluidPage(
numericInput(inputId = "A", "Number A", value = 2),
numericInput(inputId = "B", "Number B", value = 3),
numericInput(inputId = "C", "Number C [A/B]", value = 1),
textOutput("value"),
textOutput("rounded_value")
)
# Server logic
server <- function(input, output, session){
num_C <- reactiveValues(
value = NULL,
rounded_value = NULL
)
observeEvent(input$A | input$B, {
num_C$value <- input$A / input$B
num_C$rounded_value <- round(num_C$value, 1)
})
observeEvent(input$C, {
num_C$value <- input$C
num_C$rounded_value <- input$C
})
output$value <- renderText(
sprintf("Number C = %f", num_C$value)
)
output$rounded_value <- renderText(
sprintf("Number C (rounded) = %f", num_C$rounded_value)
)
}
# Complete app with UI and server components
shinyApp(ui, server)
这个想法是使用reactiveValues
来跟踪数字C的完整精度和舍入值。
numericInput
将正确计算(并显示)textOutput
中C的全精度和舍入数字。numericInput
还将正确显示textOutput
中的全精度数字(等于四舍五入的数字)。 但是,当数字A和B更改时,我无法使用updateNumericInput
用舍入后的数字更新C的值。
待续...
答案 1 :(得分:2)
我只是通过为保留实际值的flag
添加一个observeEvent
和一个value <- reactiveValue()
来稍微更改了Maurits的代码。现在,“ C”将始终显示四舍五入的值,但是value
将存储实际值。
我希望这是有用的...
library(shiny)
# Define UI
ui <- fluidPage(
numericInput(inputId = "A", "Number A", value = 2),
numericInput(inputId = "B", "Number B", value = 2),
numericInput(inputId = "C", "Number C [A/B]", value = 1),
textOutput("value"),
textOutput("rounded_value")
)
# Server logic
server <- function(input, output, session){
value <- reactiveVal(1)
rounded_value <- reactiveVal()
flag <- reactiveVal(T)
observeEvent(input$A | input$B, {
value(input$A / input$B)
rounded_value(round(value(), 2))
})
observeEvent(input$C, {
if(flag()){
value(input$C)
rounded_value(round(input$C, 2))
}else{
flag(T)
}
})
observeEvent(value(),{
flag(F)
updateNumericInput(session, "C", value = rounded_value())
})
output$value <- renderText(
sprintf("Number C = %f", value())
)
output$rounded_value <- renderText(
sprintf("Number C (rounded) = %f", rounded_value())
)
}
# Complete app with UI and server components
shinyApp(ui, server)
答案 2 :(得分:2)
最简单的方法是计算input$C
的长度并应用舍入数字-同时将真实值保存为虚拟变量:
library(shiny)
#this counts the decimal places of a value
decimalplaces <- function(x) {
if ((x %% 1) != 0) {
nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed=TRUE)[[1]][[2]])
} else {
return(0)
}
}
# Define UI
ui <- fluidPage(
numericInput(inputId = "A", "Number A", value = 2),
numericInput(inputId = "B", "Number B", value = 3),
numericInput(inputId = "C", "Number C [A/B]", value = 1)
)
# Server logic
server <- function(input, output, session){
num_C <- reactiveValues(
value = NULL
)
observeEvent(input$A|input$B,{
num_C$value <- input$A/input$B
updateNumericInput(
inputId = "C",
session = session,
value = round(num_C$value,2)
)
})
observeEvent(input$C, {
#identify if num_C is greater than 2 dc
if(decimalplaces(input$C)>2){
num_C$value <- input$C
}
updateNumericInput(
inputId = "C",
session = session,
value = round(num_C$value,2)
)
})
#check that everything is working correctly.
observeEvent( input$A|input$B|input$C,{
print(paste0(num_C$value," ", input$C))
})
}
# Complete app with UI and server components
shinyApp(ui, server)
感谢@Maurits Evers提供的大部分代码。