下面的 R Shiny 代码使用包
rhandsontable
,通过函数 row_decimals()
保留完整的小数精度。作为下一步,我尝试将这些值显示为百分比,同时保留完整的小数精度。我使用 format()
或自定义 JavaScript 渲染器尝试过的所有操作都会舍入或截断渲染值,这是我不想要的。理想情况下,任何小于或等于 2 位小数的值均以 2 位小数显示(例如,0.20、0.212、0.2123 分别显示为 20.00%、21.20% 和 21.23%)以及任何大于 2 位小数的值显示所有小数(例如,0.123456789 显示为 12.3456789%)。对于如何做到这一点有什么建议吗?如下图所示。
代码:
library(shiny)
library(rhandsontable)
# Calculates decimal places for each value in specified column
row_decimals <- function(df, col_name) {
col <- df[[col_name]]
n_digits <- sapply(col, function(x) {
nchar(gsub(".*\\.|^[^.]+$", "", as.character(x)))
})
return(n_digits)
}
ui <- fluidPage(
br(),
rHandsontableOutput("myTable"),
br(),
textOutput("productOutput")
)
server <- function(input, output) {
values <- reactiveValues(data = data.frame(Values = c(0.5, 0.123456789)))
observeEvent(input$myTable, {values$data <- hot_to_r(input$myTable)})
output$myTable <- renderRHandsontable({
data <- values$data
decimals <- row_decimals(data, 'Values')
data$Values <- mapply(function(x,d){format(x, nsmall = d)},data$Values,decimals)
rhandsontable(data)
})
output$productOutput <- renderText({
product <- as.numeric(values$data$Values[1]) * as.numeric(values$data$Values[2])
paste("Product of the two rows: ", product)
})
}
shinyApp(ui = ui, server = server)
有一个非常好的用于数字格式化的 JavaScript 库,即 d3.format。您可以在数字渲染器的帮助下将其用于手动操作:
library(shiny)
library(rhandsontable)
ui <- fluidPage(
tags$head(
# https://github.com/d3/d3-format
tags$script(src = "https://cdn.jsdelivr.net/npm/d3-format@3")
),
br(),
rHandsontableOutput("myTable"),
br(),
textOutput("productOutput")
)
server <- function(input, output) {
dat <- data.frame(Values = c(0.5, 0.123456789))
output$myTable <- renderRHandsontable({
rhandsontable(dat) %>%
hot_col(
1,
renderer = "function(instance, td, row, col, prop, value, cellProperties) {
Handsontable.renderers.NumericRenderer.apply(this, arguments);
const p = Math.max(0, d3.precisionFixed(0.0005) - 2);
const f = d3.format('.' + p + '%');
td.innerHTML = f(value);
}"
)
})
output$productOutput <- renderText({
dd <- hot_to_r(input$myTable)
product <- dd$Values[1] * dd$Values[2]
paste("Product of the two rows: ", product)
})
}
shinyApp(ui = ui, server = server)
我不明白这行代码
p = Math.max(0, d3.precisionFixed(0.0005) - 2)
,我是从示例中复制的。
此代码完全解决了该请求,其中至少显示 2 位小数,并且以填充精度显示值。
library(shiny)
library(rhandsontable)
ui <- fluidPage(
br(),
rHandsontableOutput("myTable"),
br(),
textOutput("numericOutput")
)
server <- function(input, output) {
inputs <- reactiveValues(data = data.frame(Values = c(50, 12.3456789)))
observeEvent(input$myTable, { inputs$data <- hot_to_r(input$myTable) })
adjVals <- reactive({ as.numeric(inputs$data$Values) / 100 })
output$myTable <- renderRHandsontable({
data <- inputs$data
# Simplified formatting logic
data$Values <- sapply(data$Values, function(x) {
n_decimals <- nchar(sub("^[^.]*\\.", "", as.character(x)))
n_decimals <- max(2, n_decimals) # Ensure at least 2 decimal places
formatC(x, format = "f", digits = n_decimals)
})
rhandsontable(data) %>%
hot_col(1, renderer = "
function(instance, td, row, col, prop, value, cellProperties) {
Handsontable.renderers.NumericRenderer.apply(this, arguments);
td.style.textAlign = 'right'; // Right align text
if(value) {
let formattedValue = value.toString();
let parts = formattedValue.split('.');
parts[1] = parts[1] || ''; // Ensure there is a decimal part
td.innerHTML = parts[0] + '.' + parts[1].padEnd(2, '0') + '%';
}
}
")
})
output$numericOutput <- renderText({
product <- adjVals()[1] * adjVals()[2]
row2 <- adjVals()[2]
paste("Product of the two rows: ", product, "; Row 2 value is:", row2)
})
}
shinyApp(ui = ui, server = server)
输出: