I have a data frame that contains ~15 variables of interest, and I'm aiming to conditionally fill the values based on some criteria using the pill_buttons()
function in the reactablefmtr
package.
The dummy data below attempts to simulate my real data, but for the purpose of this post, I've just gone with 3 variables instead of 15 or so. var1_z
, var2_z
etc. are z-scores that correspond to their namesake column. I then create additional columns that reference the colour I'd like the respective values to be coloured in the table.
library(tidyverse)
library(reactable)
library(reactablefmtr)
cell_bg <- function(x){
case_when(
x > 1.5 ~ "red",
x < -1.5 ~ "lightblue",
.default = "transparent"
)
}
set.seed(1)
ex <- data.frame(
date = seq(Sys.Date(), Sys.Date() - 9, -1),
var1 = round(rnorm(10, 8000, 500)),
var2 = round(rnorm(10, 500, 50)),
var3 = round(rnorm(10, 100, 20)),
var1_z = round(runif(10, -3, 3), 2),
var2_z = round(runif(10, -3, 3), 2),
var3_z = round(runif(10, -3, 3), 2)
) %>%
mutate(
across(
.cols = var1_z:var3_z,
.fns = cell_bg,
.names = "{.col}_pal"
)
)
I'm familiar with how to use the pill_buttons()
function, as displayed below on my dummy data set. However, its repetitive and tedious to complete each function for each variable as I have below, as well as coding colDef(show = FALSE)
for every column I wish not to display in the final output. As I'm sure you can understand, having to repeat these steps for many more columns seems overkill.
reactable(ex,
highlight = TRUE,
pagination = FALSE,
defaultColDef = colDef(
align = "center",
headerVAlign = "center",
html = TRUE
),
columns = list(
date = colDef(sticky = "left"),
var1 = colDef(cell = pill_buttons(ex, color_ref = "var1_z_pal")),
var2 = colDef(cell = pill_buttons(ex, color_ref = "var2_z_pal")),
var3 = colDef(cell = pill_buttons(ex, color_ref = "var3_z_pal")),
var1_z = colDef(show = FALSE),
var2_z = colDef(show = FALSE),
var3_z = colDef(show = FALSE),
var1_z_pal = colDef(show = FALSE),
var2_z_pal = colDef(show = FALSE),
var3_z_pal = colDef(show = FALSE)
)
)
I know I can use other table packages, such as kableExtra
that may streamline my workflow, but I'm set on using reactablefmtr
and the pill_buttons()
function as I like the aesthetic. I'm hoping someone may have a solution where I can make my code to create the desired output more efficient without having to write many, many lines.
Here is an example where every colDef(show = FALSE)
and every colDef(cell = pill_buttons(...))
is generated dynamically without writing it down for every relevant column. This can be extended to an arbitrary number of columns.
We use lapply
here in order to generate a list containing the different colDef
and additionally name these list entries such that they match the relevant column names.
library(tidyverse)
library(reactable)
library(reactablefmtr)
# columns with coldef(show = FALSE)
colsNotShow <- ex |> select(contains("z")) |> colnames()
# generate coldef for these ones
coldefs <- lapply(1:length(colsNotShow), \(x) colDef(show = FALSE))
names(coldefs) <- colsNotShow
# columns with pill_buttons function
colsShowPillButtons <- ex |> select(starts_with("var") & !contains("z")) |> colnames()
coldefsShowPillButtons <- lapply(colsShowPillButtons,
\(x) colDef(
cell = pill_buttons(ex,
color_ref = paste0(
x,"_z_pal"))))
names(coldefsShowPillButtons) <- colsShowPillButtons
# combine them and add the date colDef
coldefs <- c(coldefs, coldefsShowPillButtons, list(date = colDef(sticky = "left")))
reactable(ex,
highlight = TRUE,
pagination = FALSE,
defaultColDef = colDef(
align = "center",
headerVAlign = "center",
html = TRUE
),
columns = coldefs)
Result:
Data:
cell_bg <- function(x){
case_when(
x > 1.5 ~ "red",
x < -1.5 ~ "lightblue",
.default = "transparent"
)
}
set.seed(1)
ex <- data.frame(
date = seq(Sys.Date(), Sys.Date() - 9, -1),
var1 = round(rnorm(10, 8000, 500)),
var2 = round(rnorm(10, 500, 50)),
var3 = round(rnorm(10, 100, 20)),
var1_z = round(runif(10, -3, 3), 2),
var2_z = round(runif(10, -3, 3), 2),
var3_z = round(runif(10, -3, 3), 2)
) %>%
mutate(
across(
.cols = var1_z:var3_z,
.fns = cell_bg,
.names = "{.col}_pal"
)
)