Skip to content

should options ggplot2.discrete.fill behave the same as scale_fill_manual #6569

@wvictor14

Description

@wvictor14

Hi,

I have a use-case where it is convenient to set a color palette for my graphics globally for my project. I have lots of plots created by ggplot and thus I chose the strategy to use ggplot2's functionality of setting globally defined color palettes via options(ggplot2.discrete.colour), rather than adding a scale_colour_manual call to each plot call.

In my use-case I am using named vector to map levels of each factor to some colour. Also, in some of these plots the data is subsetted before plotting, such that some of elements in the named palette vector are not needing to be used. I thought this would be a smart use-case because I know scale_*_manual + named vector will utilize only those elements that have a name that matches the levels of the mapped variable.

Example, this works well with the scale_*_manual functionality:

library(ggplot2)
library(dplyr)
mpg_filt <- mpg |> filter(class %in% c('2seater', 'compact'))
cty_by_var <- function(var) {
  ggplot(mpg_filt, aes(cty, fill = factor({{var}}))) +
    geom_density(alpha = 0.5)
}

named_vector3 <- c(
  'midsize' = 'orange',   # not in subset
  'pickup' = 'green',      # also not in subset
  '2seater' = 'blue', 
  'compact' = 'red'
)

cty_by_var(class) + scale_fill_manual(values = named_vector3)
Image

But, it is tedious to write +scale_fill_manual across all my custom plot functions. I thought this would be a good case to try the options + ggplot2.discrete.fill functionality.

But for some reason the names don't get matched when trying with the options & ggplot2.discrete.* approach:

withr::with_options(
  list(ggplot2.discrete.fill = named_vector3),
  print(cty_by_var(class))
)
Image

I can see that the same behaviour occurs with using this over-spec'd named vector to type in scale_fill_discrete:

cty_by_var(class) + scale_fill_discrete(type = named_vector3)

I find this behaviour to be unintuitive, why does providing a named vector to scale_*_manual result in different behaviour than when providing the same palette to options(ggplot2.discrete.*) or scale_*_discrete?

If it is intended, then I think the documentation could be improved, because the wording between scale_colour_discrete and scale_colour_manual to be too similar (implying similar/identical behaviour):

scale_color_discrete

type

One of the following:

    A character vector of color codes. The codes are used for a 'manual' color scale as long as the number of codes exceeds the number of data levels (if there are more levels than codes, [scale_colour_hue()](https://ggplot2.tidyverse.org/reference/scale_hue.html)/[scale_fill_hue()](https://ggplot2.tidyverse.org/reference/scale_hue.html) are used to construct the default scale). If this is a named vector, then the color values will be matched to levels based on the names of the vectors. Data values that don't match will be set as na.value.

vs
'scale_color_manual'

values
a set of aesthetic values to map data values to. The values will be matched in order (usually alphabetical) with the limits of the scale, or with breaks if provided. If this is a named vector, then the values will be matched based on the names instead. Data values that don't match will be given na.value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions