Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot: How to create a discrete color palette that fits the data automatically?

Tags:

r

ggplot2

I have a customized function that I use for all my plots instead of the plain ggplot:

my_ggplot <- function(...){
    ggplot(...) +
    theme_bw() +
    scale_colour_manual(values=get_palette(20)) +
    theme(axis.text.x=element_text(size=15),
          axis.text.y=element_text(size=15),
          axis.title.y=element_text(vjust=-.5, size=15, face="bold"),
          axis.title.x=element_text(vjust=-.5, size=15, face="bold"),
          plot.title=element_text(vjust=1, size=18, face="bold"),
          legend.title=element_text(size=15, face="bold"),
          plot.margin=unit(c(2,1,2,2), "lines")) # T R B L
}

Now I can do something like:

my_ggplot(molten_df, aes(timepoint,count,group=gene_symbol)) +
    geom_line(aes(color=gene_symbol), lwd=1.5)

This gives me decent label font sizes and my own color scale. Unfortunately I have to manually encode the palette size (20) to my get_palette function, which returns a different palette depending on the number I pass it.

My question: is there a way to infer the number of levels that the color aesthetic will have so my_ggplot doesn't crash when I need to plot 21 colors? I guess this is the way ggplot does it, but I can't seem to find the relevant function in their source code.

Answered by @user946850 This is what I ended up doing:

my_ggplot <- function(...){
    ggplot(...) +
    theme_bw() +
    discrete_scale("colour", "my_scale", dyn_palette()) +
    theme(axis.text.x=element_text(size=15),
          axis.text.y=element_text(size=15),
          axis.title.y=element_text(vjust=-.5, size=15, face="bold"),
          axis.title.x=element_text(vjust=-.5, size=15, face="bold"),
          plot.title=element_text(vjust=1, size=18, face="bold"),
          legend.title=element_text(size=15, face="bold"),
          plot.margin=unit(c(2,1,2,2), "lines")) # T R B L
}

dyn_palette <- function(){
  function(n){
    get_palette(n)
  }
}
like image 583
nachocab Avatar asked Dec 21 '12 18:12

nachocab


People also ask

How do I specify colors in ggplot2?

A color can be specified either by name (e.g.: “red”) or by hexadecimal code (e.g. : “#FF1234”).

What is ggplot default palette?

By default, ggplot graphs use a black color for lines and points and a gray color for shapes like the rectangles in bar graphs.

Is ggplot colorblind friendly?

More specifically, ggpubfigs contains six color palettes that are colorblind friendly and aim to increase the accessibility of scientific figures and eight themes that modify 21 parameters of a default ggplot2 figure.

Which R package can we use to add compelling color schemes to our visualizations?

The R package ggsci contains a collection of high-quality color palettes inspired by colors used in scientific journals, data visualization libraries, and more.


1 Answers

I'm afraid scale_colour_manual isn't the way to go here. Let's take a look behind the scenes: How does it work for, say, the Brewer scales?

If you look at the definition of scale_colour_brewer, you will see that it is just a call to

discrete_scale("colour", "brewer", brewer_pal(type, palette), ...)

Now let's take a look at brewer_pal (in the scales package):

> brewer_pal
function (type = "seq", palette = 1) 
{
    pal <- pal_name(palette, type)
    function(n) {
        brewer.pal(n, pal)[seq_len(n)]
    }
}

Interesting, right? A function that returns a (bound) function with one argument n -- that's where the number of levels is going to be passed when the plot is created. In turn, brewer.pal (in RColorBrewer) just returns a list of colors:

> brewer.pal(3, 'YlOrRd')
[1] "#FFEDA0" "#FEB24C" "#F03B20"

You should be able to achieve just the same with your custom palette by following this pattern.

like image 58
krlmlr Avatar answered Sep 23 '22 02:09

krlmlr