Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot2 positive and negative values different color gradient

Tags:

r

ggplot2

I am using R (3.0.1), and ggplot2 (0.9.3.1). I have data that contains both positive and negative values, and I want to obtain a geom_tile plot in which there are different color scale gradients for the positive and the negative numbers (e.g., positive numbers go from red to yellow, negative numbers from blue to cyan). I am able to approach what I want using scale_fill_gradientn (see below), but this results in one continuous gradient that includes "white" color at the midpoint (0). I need to avoid these midpoint colors, and therefore somehow need to "break" the gradients at zero. In other words, I need two continuous gradients (one for positive values, one for negative values) that have a discrete break at zero. Any help?

dat <- data.frame(Row = rep(x = LETTERS[1:5], times = 10)
 , Col = rep(x = LETTERS[1:10], each = 5)
 , Y = runif(n = 50, min = -1, max = 1))

p <- ggplot(data =  dat, aes(x = Row, y = Col)) + 
  geom_tile(aes(fill = Y)) +
  scale_fill_gradientn(colours=c("blue","cyan","white", "yellow","red"), values=rescale(c(-1,0,1)))
like image 651
Niels Janssen Avatar asked Sep 09 '13 14:09

Niels Janssen


3 Answers

Make the range between the cyan and yellow very very small:

ggplot(data =  dat, aes(x = Row, y = Col)) + 
  geom_tile(aes(fill = Y)) +
  scale_fill_gradientn(colours=c("blue","cyan","white", "yellow","red"), 
    values=rescale(c(-1,0-.Machine$double.eps,0,0+.Machine$double.eps,1)))

enter image description here

The guide does not have a physical break in it, but the colors map as you described.

like image 73
Brian Diggs Avatar answered Nov 20 '22 01:11

Brian Diggs


I'm not sure what version of ggplot2 this was added, but there is now built in functionality for this:

p <- ggplot(data =  dat, aes(x = Row, y = Col)) + 
    geom_tile(aes(fill = Y)) +
    scale_fill_gradient2()
like image 11
Keith Avatar answered Nov 20 '22 00:11

Keith


You can always pad the results by a little bit when graphing in order to avoid the white range entirely and exclusively show light yellow and light cyan for numbers right around 0:

dat$Y2 <- ifelse(dat$Y > 0, dat$Y + .25, ifelse(dat$Y < 0, dat$Y-.25,dat$Y))
like image 2
thompsor Avatar answered Nov 20 '22 01:11

thompsor