Diagonal labels orientation on x-axis in heatmap(s)

To fix pheatmap, all you really want to do is to go into pheatmap:::draw_colnames and tweak a couple of settings in its call to grid.text(). Here's one way to do that, using assignInNamespace(). (It may need additional adjustments, but you get the picture ;):

library(grid)     ## Need to attach (and not just load) grid package
library(pheatmap)

## Your data
d <- matrix(rnorm(25), 5, 5)
colnames(d) = paste("bip", 1:5, sep = "")
rownames(d) = paste("blob", 1:5, sep = "")

## Edit body of pheatmap:::draw_colnames, customizing it to your liking
draw_colnames_45 <- function (coln, ...) {
    m = length(coln)
    x = (1:m)/m - 1/2/m
    grid.text(coln, x = x, y = unit(0.96, "npc"), vjust = .5, 
        hjust = 1, rot = 45, gp = gpar(...)) ## Was 'hjust=0' and 'rot=270'
}

## For pheatmap_1.0.8 and later:
draw_colnames_45 <- function (coln, gaps, ...) {
    coord = pheatmap:::find_coordinates(length(coln), gaps)
    x = coord$coord - 0.5 * coord$size
    res = textGrob(coln, x = x, y = unit(1, "npc") - unit(3,"bigpts"), vjust = 0.5, hjust = 1, rot = 45, gp = gpar(...))
    return(res)}

## 'Overwrite' default draw_colnames with your own version 
assignInNamespace(x="draw_colnames", value="draw_colnames_45",
ns=asNamespace("pheatmap"))

## Try it out
pheatmap(d)

enter image description here


It is a little more complex than my comment presumed, because heatmap breaks up the plotting region in order to draw the dendrograms and the last plot region is not the image plot to which you want to attach the labels.

There is a solution though as heatmap provides the add.expr argument which takes an expression to be evaluated when the image is drawn. One also needs to know the reordering of the labels that takes place due to the dendrogram ordering. The last bit involves a bit of an inelegant hack as I will draw the heatmap first to get the reordering information and then use that to draw the heatmap properly with the angled labels.

First an example from ?heatmap

 x  <- as.matrix(mtcars)
 rc <- rainbow(nrow(x), start = 0, end = .3)
 cc <- rainbow(ncol(x), start = 0, end = .3)
 hv <- heatmap(x, col = cm.colors(256), scale = "column",
               RowSideColors = rc, ColSideColors = cc, margins = c(5,10),
               xlab = "specification variables", ylab =  "Car Models",
               main = "heatmap(<Mtcars data>, ..., scale = \"column\")")

At this stage, the labels aren't how we want them, but hv contains the information we need to reorder the colnames of mtcars in its component $colInd:

> hv$colInd
 [1]  2  9  8 11  6  5 10  7  1  4  3

You use this like you would the output from order e.g.:

> colnames(mtcars)[hv$colInd]
 [1] "cyl"  "am"   "vs"   "carb" "wt"   "drat" "gear" "qsec" "mpg"  "hp"  
[11] "disp"

Now use that to generate the labels we want in the correct order:

 labs <- colnames(mtcars)[hv$colInd]

Then we re-call heatmap but this time we specify labCol = "" to suppress the labelling of the column variables (using zero length strings). We also use a call to text to draw the labels at the desired angle. The call to text is:

text(x = seq_along(labs), y = -0.2, srt = 45, labels = labs, xpd = TRUE)

which is essentially what you have in your question. Play with the value of y as you need to adjust this to the length of the strings so as to have the labels not overlap with the image plot. We specify labels = labs to pass in the labels we want draw in the order required. The entire text call is passed to add.expr unquoted. Here is the entire call:

 hv <- heatmap(x, col = cm.colors(256), scale = "column",
               RowSideColors = rc, ColSideColors = cc, margins = c(5,10),
               xlab = "specification variables", ylab =  "Car Models",
               labCol = "",
               main = "heatmap(<Mtcars data>, ..., scale = \"column\")",
               add.expr = text(x = seq_along(labs), y = -0.2, srt = 45,
                               labels = labs, xpd = TRUE))

Which results in:

enter image description here


I am also looking for method to rotate label text with heatmap. Eventually I have managed to find this solution:

library(gplots)

library(RColorBrewer)

heatmap.2(x,col=rev(brewer.pal(11,"Spectral")),cexRow=1,cexCol=1,margins=c(12,8),trace="none",srtCol=45)

The key argument is srtCol(or srtRow for row labels), which is used to rotate column labels in gplots.