formattable 中的动态条件

Dynamic conditions in formattable

我正在使用 formattable 在 shiny 应用程序的 table 中实现一些条件颜色格式。例如,假设我想为低于值 2 的单元格着色,绿色,高于 5 的单元格,红色,2 和 5 之间的单元格,橙色。我会这样写我的格式化函数:

formatter(
  "span", 
  style = x ~ style(
  color = 'white',
  'background-color' =  
    ifelse(x > 5, "red",
      ifelse(x > 2 & x <= 5, "orange",
        "green"))))

但是,我真正想做的是让用户能够更改这些颜色阈值,即 2 和 5。

假设 user_low 和 user_high 由用户定义:

col_format <- 
  formatter(
      "span", 
      style = x ~ style(
      color = 'white',
      'background-color' =  
        ifelse(x > input$user_high, "red",
          ifelse(x > input$user_low & x <= input$user_high, "orange",
            "green"))))

如果我现在尝试将此格式化程序输入我闪亮的应用程序中的格式table:

formattable(mtcars, col_format)

我收到以下错误:

'col_format' of mode 'function' was not found

看似 input$user_low 和 input$user_high 未被评估,而是在格式化程序中被视为字符串。我试过 eval(), eval(parse()), 都没有用。

有什么想法吗?

您的代码几乎可以正常运行,但是如果您想在表达式中使用 input$user_high 等输入元素,则必须使用 reactive.

这将按顺序发生:

  1. 输入元素的值发生变化。 (input$user_lowinput$user_high
  2. 列格式化条件 (col_format) 将更新,因为它的依赖关系发生了变化。
  3. 重新渲染 dataTableOutput 因为它依赖于 col_format

示例代码:

library(shiny)
library(formattable)
library(DT)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      numericInput("user_low", "User low", value = 2, min = 1, max = 5),
      numericInput("user_high", "User high", value = 8, min = 6, max = 10)
    ),

    mainPanel(
      DT::dataTableOutput("table")
    )
  )
)

server <- function(input, output) {
  output$table <- DT::renderDataTable( {
    as.datatable(formattable(mtcars, list(
      cyl = col_format()
    )))
  })

  col_format <- reactive( {
    formatter(
      "span",
      style = x ~ style(
        color = 'white',
        'background-color' =
          ifelse(x > input$user_high, "red",
                 ifelse(x > input$user_low & x <= input$user_high, "orange",
                        "green"))))
  })

}

shinyApp(ui, server)

编辑:要将格式化程序应用于每一列(根据您的评论),您可以使用 lapply,如 动态生成Formattable vignette 中的格式化程序 部分。下面的代码将格式应用于整个数据集。

代码:

output$table <- DT::renderDataTable( {
  as.datatable(formattable(mtcars, lapply(1:ncol(mtcars), function(col) {
    area(row = 1:nrow(mtcars), col) ~ col_format() 
  })))
})