18

I'm using gplot to produce a heatmap showing log2-fold changes of a treatment groups versus paired controls. With the following code:

 heatmap.2(as.matrix(SeqCountTable), col=redgreen(75), 
           density.info="none", trace="none", dendrogram=c("row"), 
            symm=F,symkey=T,symbreaks=T, scale="none") 

I output a heat map with real fold change values (i.e., non Row-Z score) which is what I'm after, in the Red-Black-Green color scheme that is every biologist's favorite!

https://i.stack.imgur.com/uhFbP.jpg

The actual range of log2-fold change is -3/+7, with many values in the -2/-1 and +1/+2 range, which appear as dark red/green (respectively). This makes the whole heatmap quite dark and so difficult to interpret.

  • Is there a way of skewing the color gradient to make it less linear? That is, so that the gradient from black to quite bright occurs over a smaller range?
  • And / or change the color range to be asymmetric, i.e., to run from -3/+7, as the data does, rather than -7/+7 as the scale currently does, with black still centered on zero?
gung - Reinstate Monica
  • 11,583
  • 7
  • 60
  • 79
Lippy
  • 373
  • 1
  • 2
  • 9
  • 12
    Please don't use the red-green scheme in anything that is supposed to be shown to someone else. 8% males and 0.5% females suffer from color impairment and will have trouble reading your heatmap. http://designshack.net/articles/accessibility/tips-for-designing-for-colorblind-users/ – January Jan 14 '15 at 15:53

4 Answers4

18

I got the color range to be asymmetric simply by changing the symkey argument to FALSE

symm=F,symkey=F,symbreaks=T, scale="none"

Solved the color issue with colorRampPalette with the breaks argument to specify the range of each color, e.g.

colors = c(seq(-3,-2,length=100),seq(-2,0.5,length=100),seq(0.5,6,length=100))

my_palette <- colorRampPalette(c("red", "black", "green"))(n = 299)

Altogether

heatmap.2(as.matrix(SeqCountTable), col=my_palette, 
    breaks=colors, density.info="none", trace="none", 
        dendrogram=c("row"), symm=F,symkey=F,symbreaks=T, scale="none")
zx8754
  • 52,746
  • 12
  • 114
  • 209
Lippy
  • 373
  • 1
  • 2
  • 9
  • What I am confusing is that after you change the non-equal breaks for different colors, it would be difficult to explain the heatmap result, right? since, they are not equally continuous? – Shicheng Guo Mar 11 '17 at 01:30
  • Another problem is, if you set the colors like this way, The key seems always be abnormal (not shown in the topright of the heatmap figure). Do you find such problem before? – Shicheng Guo Mar 11 '17 at 01:34
15

You could try to create your own color palette using the RColorBrewer package

my_palette <- colorRampPalette(c("green", "black", "red"))(n = 1000)

and see how this looks like. But I assume in your case only scaling would help if you really want to keep the black in "the middle". You can simply use my_palette instead of the redgreen()

I recommend that you check out the RColorBrewer package, they have pretty nice in-built palettes, and see interactive website for colorbrewer.

zx8754
  • 52,746
  • 12
  • 114
  • 209
  • It worked for me back then, you'd have to use this color palette as a function argument of course (`col=my_palette`) –  Sep 26 '16 at 18:03
2

I think you need to set symbreaks = FALSE That should allow for asymmetrical color scales.

2

Here's another option for those not using heatmap.2 (aheatmap is good!)

Make a sequential vector of 100 values from min to max of your input matrix, find value closest to 0 in that, make two vector of colours to and from desired midpoint, combine and use them:

breaks <- seq(from=min(range(inputMatrix)), to=max(range(inputMatrix)), length.out=100)
midpoint <- which.min(abs(breaks - 0))
rampCol1 <- colorRampPalette(c("forestgreen", "darkgreen", "black"))(midpoint)
rampCol2 <- colorRampPalette(c("black", "darkred", "red"))(100-(midpoint+1))
rampCols <- c(rampCol1,rampCol2)
bruce.moran
  • 347
  • 2
  • 10