tjebo
tjebo

Reputation: 23767

change direction of fill/ color aesthetic of default palette

On pondering on this very recent question I noticed that reversing the factor levels does naturally not change the order of colors. I tried to add direction = -1 in scale_fill/scale_color ("_discrete" and "_hue"), and was stunned by the weird result. I am not sure if there are more recent questions than this thread, but the given code does produce the following weird result (regardless of the h.start argument). The same happens with fill

Bug? Or am I overlooking something?

(P.s. I don't really like the default colors and am never really using them. This is more of an academic question)

library(ggplot2)

ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_point() + 
  scale_color_discrete(direction = -1)

Created on 2020-02-04 by the reprex package (v0.3.0)

devtools::session_info()
#>  version  R version 3.6.2 (2019-12-12)
#>  ggplot2     * 3.2.1   2019-08-10 [1] CRAN (R 3.6.1)

Upvotes: 0

Views: 1645

Answers (1)

user12728748
user12728748

Reputation: 8506

I believe it is a bug in the scales::hue_pal function. In that help page, one example is show_col(hue_pal(direction = -1)(9)), which (on my machine) gives the same color as in your example in all 9 tiles - and that is certainly not the intended outcome. It seems like farver:::encode_c does not work as intended in that context.

Intuitively, I would just reverse the palette you get with direction=1, but the scales::hue_pal function generates negative hues that farver::encode_colour cannot deal with. I am not sure this is the intended outcome (just reversing the order of the palette colors), but I would adjust the scales::hue_pal function like this:

library(ggplot2)
library(scales)

hue_pal <- function (h = c(0, 360) + 15, c = 100, l = 65, h.start = 0, direction = -1) 
{
    stopifnot(length(h) == 2)
    stopifnot(length(c) == 1)
    stopifnot(length(l) == 1)
    scales:::force_all(h, c, l, h.start, direction)
    function(n) {
        if (n == 0) {
            stop("Must request at least one colour from a hue palette.", 
                call. = FALSE)
        }
        if ((diff(h)%%360) < 1) {
            h[2] <- h[2] - 360/n
        }
        rotate <- function(x) (x + h.start)%%360 * direction
        hues <- rotate(seq(h[1], h[2], length.out = n))
        if(direction == -1) hues <- abs(rev(hues)) # my edit
        hcl <- cbind(hues, c, l)
        farver::encode_colour(hcl, from = "hcl")
    }
}

scale_color_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, ...)
}


# reversed color palette
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
    geom_point() + 
    scale_color_discrete(direction = -1)

# standard palette
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
    geom_point() + 
    scale_color_discrete(direction = 1)

Created on 2020-02-04 by the reprex package (v0.3.0)

Upvotes: 1

Related Questions