I'm trying to combine the following two reactable features in R:
My goal is to highlight the aggregated (sum) group headers with different shades of orange, depending on the group sum value. This way, it's easier to spot groups with high/low values.
I use only one color range c("#ffe4cc", "#ffb54d")
for both cell values and group headers, e.g. 100
as cell value and 100
as group header result in the same color.
What I've tried so far (this is a simplified example, my real world problem needs highlighting over multiple columns/groups):
library(datasets)
library(reactable)
data('CO2')
get_orange <- function(x) rgb(colorRamp(c("#ffe4cc", "#ffb54d"))(x), maxColorValue = 255)
reactable(
CO2,
groupBy = c('Plant', 'Type', 'Treatment'),
columns = list(
conc = colDef(
aggregate = 'mean'
),
uptake = colDef(
aggregate = 'sum',
style = function(value) {
normalized <- (value - min(CO2$uptake)) / (max(CO2$uptake) - min(CO2$uptake))
color <- get_orange(normalized)
list(background = color)
}
)
)
)
Resulting in: Screenshot expected vs actual
> packageVersion('reactable')
[1] ‘0.2.3’
I found a workaround for the conditional styling in groups.
By injecting a JS function in colDef(style=) of reactable, the color of each cell can be calculated.
You can find the full example here.
For each column you want with a conditional format, you have to bypass a JS()
function, like so:
for (column in dynamic_cols){
script = paste("
// source: https://glin.github.io/reactable/articles/examples.html#grouped-cell-rendering-1
function(rowInfo) {
// source: https://stackoverflow.com/a/44134328/4856719
function hslToHex(h, s, l) {
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = n => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, '0');
};
return `#${f(0)}${f(8)}${f(4)}`;
}
var value = rowInfo.row['", column, "']
var max = ", q, "
var min = 0
// pct_value = (value - min) * 100 / (max - min)
pct_value = (Math.min(value, max) - min) * 100 / (max - min)
// If value equals 0, set font color grey.
if (value == 0) {
var color = '#adafaa'
var bg = '#fff'
} else {
var color = '#000000'
var bg = hslToHex(40, pct_value, 95 - pct_value / 2)
}
return { color: color, backgroundColor: bg}
}", sep="")
dynamic_col_def[column] <- list(colDef(
aggregate = 'sum', style = JS(script)
))
}
The injected JS function does consume rowInfo
as input parameter and returns a named list. In this case, we return text color color
and cell background color backgroundColor
.
With this workaround, you can either set a custom color range for each column in the table or combine multiple columns to one color range.
The thread on github/glin/reactable
can be found here.