Nathaniel Smith and Stéfan van der Walt presented [YouTube] a new colormap at SciPy 2015 called viridis. From the authors:

The default colourmap in Matplotlib is the colourful rainbow-map called Jet, which is deficient in many ways: small changes in the data sometimes produce large perceptual differences and vice-versa; its lightness gradient is non-monotonic; and, it is not particularly robust against color-blind viewing. Thus, a new default colormap is needed – but no obvious candidate has been found. Here, we present our proposed new default colormap for Matplotlib, and expose the theory, tools, data exploration and motivations behind its design.

You can also find out a tad more about their other designs (a.k.a. the runner-ups), including Parula which is a proprietary MATLAB color map.

Simon Garnier (@sjmgarnier) (the author of this package) took Nathaniel & Stéfan’s work and turned it into an R package.

Noam Ross (@noamross) & Bob Ruis (@hrbrmstr) piled on shortly thereafter to add some ggplot color scale_ functions.

Rather than duplicate the examples already provided in the documentation of those functions, here’s a comparison of viridis to other common color palettes used in countless R examples, packages and analyses. We create 6 strips, each filled with a different palette:

Let’s pull in the packages we’ll need:

library(viridis)
library(scales)
library(colorspace)
library(dichromat)

We’ll also make a helper function to save us some typing and setup the base # of colors in the colormap:

n_col <- 128

img <- function(obj, nam) {
  image(1:length(obj), 1, as.matrix(1:length(obj)), col=obj, 
        main = nam, ylab = "", xaxt = "n", yaxt = "n",  bty = "n")
}

We’ll take each set of 6 strips and view it through the eyes of three different types of color vision as well as a fully desaturated version.

“Normal” Vision

par(mfrow=c(6, 1), mar=rep(1, 4))
img(rev(heat.colors(n_col)), "heat")
img(rev(rainbow(n_col)), "rainbow")
img(rev(topo.colors(n_col)), "topo")
img(rev(cm.colors(n_col)), "cm")
img(gradient_n_pal(brewer_pal("seq")(9))(seq(0, 1, length=n_col)), "brewer")
img(rev(viridis(n_col)), "viridis")

If you happen to have “normal” color vision you should be drawn to the bottom two (ColorBrewer and Viridis on the right). They are both sequential and convey should appear to have more precision than the other four (and they don’t have a gap in the middle like cm does).

Take a look at each of the vision-adjusted examples:

Green-Blind (Deuteranopia)

par(mfrow=c(6, 1), mar=rep(1, 4))
img(dichromat(rev(heat.colors(n_col)), "deutan"), "heat")
img(dichromat(rev(rainbow(n_col)), "deutan"), "rainbow")
img(dichromat(rev(topo.colors(n_col)), "deutan"), "topo")
img(dichromat(rev(cm.colors(n_col)), "deutan"), "cm")
img(dichromat(gradient_n_pal(brewer_pal("seq")(9))(seq(0, 1, length=n_col)), "deutan"), "brewer")
img(dichromat(rev(viridis(n_col)), "deutan"), "viridis")

Red-Blind (Protanopia)

par(mfrow=c(6, 1), mar=rep(1, 4))
img(dichromat(rev(heat.colors(n_col)), "protan"), "heat")
img(dichromat(rev(rainbow(n_col)), "protan"), "rainbow")
img(dichromat(rev(topo.colors(n_col)), "protan"), "topo")
img(dichromat(rev(cm.colors(n_col)), "protan"), "cm")
img(dichromat(gradient_n_pal(brewer_pal("seq")(9))(seq(0, 1, length=n_col)), "protan"), "brewer")
img(dichromat(rev(viridis(n_col)), "protan"), "viridis")

Blue-Blind (Tritanopia)

par(mfrow=c(6, 1), mar=rep(1, 4))
img(dichromat(rev(heat.colors(n_col)), "tritan"), "heat")
img(dichromat(rev(rainbow(n_col)), "tritan"), "rainbow")
img(dichromat(rev(topo.colors(n_col)), "tritan"), "topo")
img(dichromat(rev(cm.colors(n_col)), "tritan"), "cm")
img(dichromat(gradient_n_pal(brewer_pal("seq")(9))(seq(0, 1, length=n_col)), "tritan"), "brewer")
img(dichromat(rev(viridis(n_col)), "tritan"), "viridis")

Desaturated

par(mfrow=c(6, 1), mar=rep(1, 4))
img(desaturate(rev(heat.colors(n_col))), "heat")
img(desaturate(rev(rainbow(n_col))), "rainbow")
img(desaturate(rev(topo.colors(n_col))), "topo")
img(desaturate(rev(cm.colors(n_col))), "cm")
img(desaturate(gradient_n_pal(brewer_pal("seq")(9))(seq(0, 1, length=n_col))), "brewer")
img(desaturate(rev(viridis(n_col))), "viridis")

Hopefully both the ColorBrewer gradient and Viridis palettes stood out as conveying the gradient colors with more precision and more consistently across all non-standard vision types as you progressed through each one.

To see this for yourself in your own work, grab the package and start subtituting viridis for some of your usual defaults to see if it makes a difference in helping you convey the story your data is trying to tell, both more accurately and for a more diverse audience.