Search code examples
rreactablereactablefmtr

How do I set the domain of a color scale using reactable/reactablefmtr?


Consider the following table using the reactable and reactablefmtr packages:

library(reactable)
library(reactablefmtr)

my_color_pal <- c("white", "red")

df <- head(mtcars[,"mpg", drop = FALSE])

reactable(
  df,
  columns = list(
    mpg = colDef(style = color_scales(df, colors = my_color_pal))
  )
)

I get this:

reactable output from code

Instead of using the current range of the mpg column, I want to set the 'domain' of the color scales where values close to zero are white and values close to 100 are red.


Solution

  • One option would be to use e.g. scales:: col_numeric to create a palette function for your desired domain. This function could then be used to add a column of colors to your dataset which could then be used to color the table cells via the color_ref argument of color_scales:

    library(reactable)
    library(reactablefmtr)
    
    my_color_pal <- c("white", "red")
    
    df <- head(mtcars[, "mpg", drop = FALSE])
    
    pal_color <- scales::col_numeric(my_color_pal, c(0, 100))
    df$color <- pal_color(df$mpg)
    
    reactable(
      df[, "mpg", drop = FALSE],
      columns = list(
        mpg = colDef(style = color_scales(df, color_ref = "color"))
      )
    )
    

    EDIT A second option to achieve the desired result would be to use a custom color scale function which following the Conditional Styling vignette could be implemented like so:

    pal_color <- function(x) rgb(colorRamp(my_color_pal, space = "Lab")(x), maxColorValue = 255)
    
    my_color_scale <- function(value, ..., domain = c(0, 100)) {
      normalized <- (value - domain[[1]]) / diff(range(domain))
      color <- pal_color(normalized)
      list(background = color)
    }
    
    reactable(
      df[, "mpg", drop = FALSE],
      columns = list(
        mpg = colDef(style = my_color_scale)
      )
    )