2

I am in the process of creating my own colour palette mainly using this blogpost.

This leads me to use ggplot's function discrete_scale(). The problem I'm running into is that I have a 9 point discrete colour scale (all really different colours, see below*). However, when I ask ggplot to draw a scale for a factor with 3 levels, it selects the first, middle and last points of the colour values. Instead what I want is to select the first 3. How do I go about this?

  • The palette I'm using is: c(#00AD2E, #29C29E, #2B8DAB, #00A1DB, #0C41ED, #8B00F5, #C724F5, #EF4E8E, #F63131, #F66223, #FA85A6, #F5910F, #F0BC00, #D6901F, #8D7F6D, #8F8F8F, #73B823, #FF4D6A, #B1652F, #1DAA76)
tjebo
  • 21,977
  • 7
  • 58
  • 94
  • related https://stackoverflow.com/questions/62462030/how-to-customize-a-color-palette-in-r-for-ggplot – tjebo Dec 20 '21 at 23:44

1 Answers1

1

The issue is that in blogpost you linked the author makes use of colorRampPalette to return an interpolated color palette for any number of colors. The first color will always be the first element and the last one the last element of the color vector you passed as input to colorRampPalette. And in case of three colors you get the mid element too.

In general the palette argument of ggplot2::discrete_scale should be a function which takes one argument n and returns n colors.

One option to achieve your desired result may look like so where besides the palette function my_pal I added a custom scale_color_my function:

Note: My simple function does not do any checks and throws no warnings e.g. in case you demand more colors than provided by the color palette. Anyway, if you want to go further I would suggest to have a look a the source code of e.g. ggplot::scale_color_brewer and scales::brewer_pal.

my_pal <- function(n) {
  cols <- c(
    "#00AD2E", "#29C29E", "#2B8DAB", "#00A1DB", "#0C41ED", "#8B00F5",
    "#C724F5", "#EF4E8E", "#F63131", "#F66223", "#FA85A6", "#F5910F", 
    "#F0BC00", "#D6901F", "#8D7F6D", "#8F8F8F", "#73B823", "#FF4D6A",
    "#B1652F", "#1DAA76"
  )
  cols[seq_len(n)]
}

scale_colour_my <- function() {
  discrete_scale("colour", "mypal", my_pal)
}
scale_color_my <- scale_colour_my

library(ggplot2)

d <- data.frame(
  x = 1:12,
  y = 1:12,
  color4 = LETTERS[1:4],
  color12 = LETTERS[1:12]
)

base <- ggplot(d, aes(x, y)) +
  geom_point() +
  scale_color_my()

base + 
  aes(color = color4)

  
base + 
  aes(color = color12)

EDIT If you want to account for multiple palettes you could follow the source code of scale_color_brewer:

my_pal <- function(palette = "my1") {
  cols <- c(
    "#00AD2E", "#29C29E", "#2B8DAB", "#00A1DB", "#0C41ED", "#8B00F5",
    "#C724F5", "#EF4E8E", "#F63131", "#F66223", "#FA85A6", "#F5910F", 
    "#F0BC00", "#D6901F", "#8D7F6D", "#8F8F8F", "#73B823", "#FF4D6A",
    "#B1652F", "#1DAA76"
  )
  pal <- if (palette == "my1") {
    cols  
  } else if (palette == "my2") {
    rev(cols)
  } else {
    cols
  }
  function(n) {
    pal[seq_len(n)]
  }
}

scale_colour_my <- function(..., palette = "my1") {
  discrete_scale("colour", "mypal", my_pal(palette = palette))
}
scale_color_my <- scale_colour_my

library(ggplot2)

d <- data.frame(
  x = 1:12,
  y = 1:12,
  color4 = LETTERS[1:4],
  color12 = LETTERS[1:12]
)

base <- ggplot(d, aes(x, y)) +
  geom_point() + 
  aes(color = color4)

base +
  scale_color_my()

base +
  scale_color_my(palette = "my2")

stefan
  • 90,330
  • 6
  • 25
  • 51
  • 1
    @tjebo. Haha. Just to follow ggplot2's NZ tradition for colo(u)r scales. (: – stefan Dec 21 '21 at 08:58
  • 1
    lol, I have actually totally overlooked the different spelling!!! I literally thought you assigned the exact same thing ... Ignore my comment :) – tjebo Dec 21 '21 at 18:14
  • Hi @stefan, thanks for your answers. I've looked at it over and over and it is really nice except for 1 thing which I cannot seem to figure out. Want I have is, similar to the blogpost, a set of multiple palettes that you can choose from. At the moment this is an argument to the function. However, the my_pal function you wrote does not take any arguments (and if you set arguments it says that 'n' is not found because you no longer specify it). Basically the result is that you now always use the same colours, instead of choosing from multiple palettes. How do you get around this? – JasperNabSq Jan 06 '22 at 13:06
  • See my edit. As I said: Have a look at the source code of `ggplot2::scale_color_brewer`. (; – stefan Jan 06 '22 at 13:28