biscale icon indicating copy to clipboard operation
biscale copied to clipboard

allow ordered factors, arbitrary dimensions in bivariate color scales

Open wpetry opened this issue 1 year ago • 0 comments

I would like to compose bivariate color scales with arbitrary dimensions to accommodate ordered factors. This feature would expand use of this package to a broader set of data that could benefit from a cross-classified color scale. For example, a bivariate color scale might allow an ordered factor (low vs. high) to be encoded as lightness or saturation variants of the other dimension's color scale.

I'm imagining a color scale that looks something like this: image

Proposed solution I think bi_class is the main function that would need modification. The style and dim would gain the option of being specified as vectors of length 2 corresponding to the argument values to use for x and y. style would also gain a new possible value, something like ordered, factor, or levels. This option would retrieve the unique values of the variable rather than trying to calculate breaks as for a continuous variable. (Add a warning here if the variable isn't ordered.)

In the above figure, this solution would look something like: bi_class(.data, x = ord, y = cont, style = c("levels", "quantile"), dim = c(2, 3))

Some careful thought is needed to ensure that the color modification for the factor doesn't cause collisions. If willing to add a dependency, colorspace has some nice functions for automating the calculation of lightened or desaturated colors for an arbitrary number of levels. An additional argument might allow the user to specify the type of color modification (lighten vs. desaturate) and the corresponding amounts of adjustment for each factor level (e.g., lightening 0 and 0.4).

Reprex The code below reproduces the figure above.

library(ggplot2)
library(colorspace)
library(patchwork)

pal <- c("#FECE65", "#E1640E", "#662506")

dat <- data.frame(y = factor(rep(c("<18", "18-45", ">45"), times = 2),
                             levels = c("<18", "18-45", ">45")),
                  x = factor(rep(c("low", "high"), each = 3),
                             levels = c("low", "high")))
dat$bi_class <- paste(as.integer(dat$x), as.integer(dat$y), sep = "-")

d <- ggplot(dat, aes(x = x, y = y, fill = bi_class))+
  geom_tile()+
  labs(title = "Desaturate", x = "[ordered factor]", y = "[continuous variable]")+
  scale_fill_manual(values = c(desaturate(pal, amount = 0.7), pal))+
  coord_equal(expand = FALSE)+
  theme_minimal()+
  theme(legend.position = "none")

l <- ggplot(dat, aes(x = x, y = y, fill = bi_class))+
  geom_tile()+
  labs(title = "Lighten", x = "[ordered factor]", y = "[continuous variable]")+
  scale_fill_manual(values = c(lighten(pal, amount = 0.4), pal))+
  coord_equal(expand = FALSE)+
  theme_minimal()+
  theme(legend.position = "none")

d + l

wpetry avatar Aug 15 '23 03:08 wpetry