I am trying to style cells in a shiny datatable into six or so column-level quantiles (except the first column, which is character). Here is a MRE of my current code, which styles cells as above or below the column mean with a rowcallback from this answer. I am not familiar with javascript.
EDIT: users can select/deselect columns, so I need a solution that applies across the columns currently in dataset
.
library(shiny)
library(DT)
set.seed(123)
dataset <- data.frame(
ID = 1:20,
Value1 = round(rnorm(10, mean = 15, sd = 5), 1),
Value2 = round(rnorm(10, mean = 25, sd = 8), 1))
ui <- fluidPage(
titlePanel("Reprex for cell styling"),
dataTableOutput("myTable"))
server <- function(input, output, session) {
output$myTable <- renderDataTable({
datatable(
dataset,
options = list(
rowCallback = JS(paste0(
"function(row, data) {n",
paste(
sapply(
2:ncol(dataset),
function(i) paste0("var value=data[", i, "]; if (value!==null) $(this.api().cell(row,", i, ").node()).css({'background-color':value <=", mean(dataset[[i]]), " ? '#6EACCA' : '#FFDD91'});n")
),
collapse = "n"
),
"}n"
))
)
)
})
}
shinyApp(ui, server)
Most of my attempts so far have been similar to:
rowCallback = JS(paste0("function(row, data) {n",
" // Iterate over columns starting from the second column (index 1)n",
sapply(2:ncol(dataset), function(i) {
paste0(
" var value = data[", i, "];n",
" if (value !== null) {n",
" // Calculate column-level quantiles for the current columnn",
" var columnData = data.map(function(row) { return row[", i, "]; });n",
" var quantiles = quantile(columnData, [0, 0.2, 0.4, 0.6, 0.8, 1]);n",
" var color;n",
" if (value <= quantiles[1]) color = '#BFD3E6';n",
" else if (value <= quantiles[2]) color = '#8BACD6';n",
" else if (value <= quantiles[3]) color = '#6382C1';n",
" else if (value <= quantiles[4]) color = '#385FAD';n",
" else if (value <= quantiles[5]) color = '#0D3D99';n",
" else color = ''; // Handle edge cases if neededn",
" $(this.api().cell(row, ", i, ").node()).css({'background-color': color});n",
" }n"
)
}), "}n"))
The closest I have gotten is styling in six quantiles but the cutoffs revert to whole-datatable values instead of column-level quantiles.
2
Answers
Got this working with help from @StéphaneLaurent's answers above and here. Using a list of quantiles for current columns and a styling loop:
You can use the DT functions
formatStyle
andstyleInterval
: