I have some example data below where I'm trying to conditionally format all numeric columns in my reactable
table but only for row 1. For example, I'd like to use a traffic light system and assign the cell backgrounds in row 1 as green, red or orange if the value is more than that in row 2, within 10% of row 2 or more than 10% below the values in row 2, respectively.
library(reactable)
set.seed(1)
name <- c("Player A", "Player B", "Team")
var1 <- rnorm(3, 1000, 200)
var2 <- rnorm(3, 1000, 200)
var3 <- rnorm(3, 1000, 200)
d <- data.frame(name, var1, var2, var3)
reactable(d,
defaultColDef = colDef(
align = "center",
format = colFormat(digits = 1)
)
)
I'm familiar with something like the below code, but I'm not sure how I can apply something like this to only specific rows and for multiple columns without repeating the function several times in colDef()
.
reactable(sleep[1:6, ], columns = list(
extra = colDef(
style = function(value) {
if (value > 0) {
color <- "#008000"
} else if (value < 0) {
color <- "#e00000"
} else {
color <- "#777"
}
list(color = color, fontWeight = "bold")
}
)
))
Here is one option to achieve your desired result which uses the row index
passed to the style function as a second argument to access the value of the successor row. Additionally I use lapply
to create the colDef
s for a list of column names.
library(reactable)
style_fun <- function(.data, colname) {
function(value, index) {
if (index < 2) {
successor_value <- .data[[colname]][index + 1]
if (value > successor_value) {
color <- "#008000"
} else if (value >= .9 * successor_value) {
color <- "orange"
} else if (value < .9 * successor_value) {
color <- "#e00000"
} else {
color <- "#777"
}
return(
list(color = color, fontWeight = "bold")
)
} else {
return(NULL)
}
}
}
cols <- names(d)[-1]
col_defs <- lapply(
cols, function(x)
colDef(
style = style_fun(d, x)
)
)
names(col_defs) <- cols
reactable(d,
defaultColDef = colDef(
align = "center",
format = colFormat(digits = 1)
),
columns = col_defs
)