question on ggplot2::scale_type()

I'd like to provide a custom default scale (using custom-default breaks and labels) for a variable with an S3 class that I would create.

I see that ggplot2::scale_type() might be useful here, as it returns:

A character vector of scale types. These will be tried in turn to find a default scale. For example, if scale_type returns c("foo", "bar") and the vector is used with the colour aesthetic, ggplot2 will first look for scale_colour_foo then scale_colour_bar .

Let's say that I create a package {acme}, and that this package establishes an S3 class acme_var. This package will export a method, scale_type.acme_var:

scale_type.acme_var <- function(x, ...) {
  "av"
}

I assume {ggplot2} will look for scale_x_av in the {ggplot2} namespace.

Will it also look in the {acme} namespace? Can I do anything to encourage it to look in the {acme} namespace?

Thanks!

I thought this was a very interesting question, so I thought I'd play around with it. I don't have a particularly deep understanding of what goes on behind the scenes in ggplot2, but it seemed simple enough to just try and see what happens...

library(ggplot2)

data(iris)
iris[, "elm"] <- as.character(iris[, "Species"])
class(iris[, "elm"]) <- "elmstedt"

scale_type.elmstedt <- function(x, ...) {
  c("elmstedt")
}

scale_type(iris[, "elm"])
#> [1] "elmstedt"
scale_type(iris[, "Species"])
#> [1] "discrete"

# template for scale_colour_elmstedt
scale_colour_discrete
#> function (..., h = c(0, 360) + 15, c = 100, l = 65, h.start = 0, 
#>     direction = 1, na.value = "grey50", aesthetics = "colour") 
#> {
#>     discrete_scale(aesthetics, "hue", hue_pal(h, c, l, h.start, 
#>         direction), na.value = na.value, ...)
#> }
#> <bytecode: 0x0000000013a5c328>
#> <environment: namespace:ggplot2>

scale_colour_elmstedt <- function(...,
                                  h = c(0, 360),
                                  c = 100,
                                  l = 40,
                                  h.start = 0,
                                  direction = 1,
                                  na.value = "grey50",
                                  aesthetics = "colour") {
  discrete_scale(aesthetics,
    "hue",
    scales::hue_pal(h, c, l, h.start, direction),
    na.value = na.value,
    ...
  )
}

# Plots
ggplot(iris, aes(Sepal.Width, Sepal.Length, color = Species)) +
  geom_point(size = 3)

ggplot(iris, aes(Sepal.Width, Sepal.Length, color = elm)) +
  geom_point(size = 3)

Created on 2020-09-01 by the reprex package (v0.3.0)

This honestly would have taken all of about 5 minutes to try if I had remembered hadley is a Kiwi! I originally named the function custom scale function scale_color_elmstedt, which ggplot2 was happy to ignore aside from throwing the occasional error my way for over an hour while I dug through the ggplot2 source on GitHub... So, make sure you always foullouw an "o" with a "u" our you'll be pounished four your bad behaviour. :wink:

All joking aside, if ggplot2 will pick it up out of the global environment, there's no reason I can imagine it wouldn't find it elsewhere in the search path (e.g. in a loaded package).

1 Like

Thanks for checking into this Jake, this is super!

I certainly did not mean for you (or anyone) to spend an hour on this :flushed:

This all stands to reason; I guess my homework now is to put together a wee package to confirm your theo(u)ry.

Don't worry about that. It's how we all learn. If I didn't thiink it was interesting (and doable) I certainly wouldn't have kept going. Plus, It gave me an excuse to poke around inside the ggplot2 code base a bit more.

Besides, it's 100%, completely my own fault...

It was literally right there in the question you posted.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.