Skip to content

Register default scales via themes #2691

Closed
@clauswilke

Description

@clauswilke

As previously mentioned in the discussion of #2239: It would be nice if default scales could be set via themes.

Currently, default scales are defined as functions that are named scale_aesthetic_data-type(), where aesthetic is the name of the aesthetic and data-type represents the data type, i.e., continuous, discrete, date, etc. For example, scale_colour_discrete() is the default scale function for discrete colors.

The definition of these defaults is distributed all over the scales code, because for some scales the default scale is the only scale that exists (example:

scale_alpha_discrete <- function(..., range = c(0.1, 1)) {
) whereas for others there are multiple possible ones and hence one is set as the default (example:
scale_colour_discrete <- scale_colour_hue
).

It would be nice if there were a way to change the defaults other than to change the global function definitions, and in particular if the defaults could be linked to the theme. For example, the theme could have an entry default_scales = list("scale_color_discrete" = scale_color_hue, "scale_color_continuous" = scale_color_gradient, ...) that lists the default scales to be used with this theme.

In terms of implementation, I see two problems, and it's not clear to me how much of a hurdle they might be. First, the code that searches for the default scales currently doesn't have access to the theme:

ggplot2/R/scale-type.R

Lines 1 to 20 in bcc3ae5

find_scale <- function(aes, x, env = parent.frame()) {
if (is.null(x)) {
return(NULL)
}
type <- scale_type(x)
candidates <- paste("scale", aes, type, sep = "_")
for (scale in candidates) {
scale_f <- find_global(scale, env, mode = "function")
if (!is.null(scale_f))
return(scale_f())
}
# Failure to find a scale is not an error because some "aesthetics" don't
# need scales (e.g. group), and it allows others to extend ggplot2 with
# their own aesthetics
return(NULL)
}

It is called from this function:
scales_add_defaults <- function(scales, data, aesthetics, env) {

which is called from here:
scales_add_defaults(plot$scales, data, aesthetics, plot$plot_env)

and here:
scales_add_defaults(plot$scales, data, new, plot$plot_env)

Second, it's not immediately clear to me whether we even have the complete theme by the time these functions are called. They are ultimately called in plot_build() here:

data <- by_layer(function(l, d) l$compute_aesthetics(d, plot))

If by that time the entire theme is assembled, then I assume it could be handed down through all these functions to the point where the scale is looked up. Otherwise, this proposal would be infeasible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions