1

I am building a plot and totally happy with the default color order defined by ggplot, for example:

library(ggplot2)
data(mtcars)

mtcars$brand <- gsub(' .*','',row.names(mtcars))

ggplot(mtcars,aes(x=mpg, y=hp, col=brand)) + 
  geom_point()

default plot

Now imagine I want to change the order of colors in the legend (in my example, according to the frequency of levels - but could be any other custom order). The only way I know is to manually define the order of levels:

df.freq <- as.data.frame(table(mtcars$brand))
neworder <- order(-df.freq$Freq)
mtcars$brand <- factor(mtcars$brand, levels=df.freq$Var1[neworder])

It makes the desired order but changes the colors as well. plot with changed order
What if I absolutely want to keep the original colors? For now I only came to an awkward workaround with manually re-creating the default palette, then reordering it and feeding these colors to scale_color_manual():

gg_color_hue <- function(n) { # code from https://stackoverflow.com/questions/8197559/
  hues = seq(15, 375, length = n + 1)
  hcl(h = hues, l = 65, c = 100)[1:n]
}

newcolors <- gg_color_hue(length(levels(mtcars$brand)))
newcolors <- newcolors[neworder]

ggplot(mtcars,aes(x=mpg, y=hp, col=brand)) + 
  geom_point()+
  scale_color_manual(values = newcolors)

desired result
It does the job but I'm wondering if there's any cleaner way...

Vasily A
  • 8,256
  • 10
  • 42
  • 76

1 Answers1

3

You can try the below, which doesn't require you to factor the brand column. I don't know if it is that much shorter. You assign the color according to the order you want, and use breaks in scale_manual_color to define the order:

library(scales)
mtcars$brand <- gsub(' .*','',row.names(mtcars))
legend_order = names(sort(-table(mtcars$brand)))
COLS = hue_pal()(length(lvl))
# sort alphabetically
names(COLS) = sort(legend_order)

ggplot(mtcars,aes(x=mpg, y=hp, col=brand)) + 
  geom_point()+
  scale_color_manual(values = COLS,breaks=legend_order)

enter image description here

If you are happy with the default colors, just do:

ggplot(mtcars,aes(x=mpg, y=hp, col=brand)) + 
geom_point()+
scale_color_manual(values=hue_pal()(length(legend_order)),
breaks=legend_order)
StupidWolf
  • 45,075
  • 17
  • 40
  • 72