tidyverse / ggplot2

An implementation of the Grammar of Graphics in R
https://ggplot2.tidyverse.org
Other
6.39k stars 2k forks source link

WIP: Scale palettes from theme #5946

Open teunbrand opened 2 weeks ago

teunbrand commented 2 weeks ago

This is a proof-of-concept PR for a part of #2239 and fix #4696.

It explores setting scale palettes from the theme. When a scale has a NULL palette, the palette will be retrieved from the theme. In the theme, palettes can be provided for different aesthetic/discreteness combinations. Currently, only aesthetics for which this is implemented are colour and fill.

Some demos of this mechanism:

devtools::load_all("~/packages/ggplot2")
#> ℹ Loading ggplot2

p <- ggplot(mpg, aes(displ, hwy)) +
  geom_point(aes(colour = class)) +
  discrete_scale("colour", palette = NULL)

# Using a palette function
p + theme(palette.colour.discrete = pal_viridis(option = "H"))

# Using a palette name
p + theme(palette.colour.discrete = "hue")

# Using a vector of colours
colours <- palette.colors(7, palette = "Okabe-Ito")
p + theme(palette.colour.discrete = colours)

Created on 2024-06-18 with reprex v2.1.0

The idea is that we'd have the default scales, e.g. scale_colour_discrete(), scale_colour_continuous() etc. have NULL palettes so that this mechanism kicks in. I'd still have to figure out how to do this in a backwards compatible manner though.

teunbrand commented 2 weeks ago

TODO: look into preserving current behaviour

teunbrand commented 2 weeks ago

The default colour/fill scales like scale_colour_discrete(), scale_fill_continuous() etc. now all produce a scale where palette = NULL and thus theme palettes are invoked. For that reason, we wouldn't need to invoke a special scale here:

devtools::load_all("~/packages/ggplot2/")
#> ℹ Loading ggplot2

p <- ggplot(mpg, aes(displ, hwy)) +
  geom_point(aes(colour = class)) +
  theme(
    palette.colour.discrete = pal_brewer("qual")
  )

p

The old way of specifying default scales through options() is reasonably preserved. Some areas where backwards compatibility does not hold completely:

options("ggplot2.discrete.colour" = scale_colour_viridis_d)

p

Created on 2024-06-19 with reprex v2.1.0

teunbrand commented 1 week ago

Now supports all vanilla non-position aesthetics. Extension aesthetics can be added by using register_theme_elements(), where fallback palettes can be set as part of the specifications.

devtools::load_all("~/packages/ggplot2")
#> ℹ Loading ggplot2

register_theme_elements(
  palette.foobar.discrete = function(n) seq(0.1, 1, length.out = n),
  element_tree = list(
    palette.foobar.discrete   = el_def(c("character", "numeric", "integer", "function"))
  )
)

fallback_palette("foobar", discrete = TRUE)
#> function(n) seq(0.1, 1, length.out = n)

Created on 2024-06-21 with reprex v2.1.0

I'll bump this from POC to WIP.