There are many packages that can generate heatmaps in R. WHeatmap designs a set of languages and a layer system that allows arbitrary positioning of heatmaps programmatically. This is a tutorial on the usage of wheatmap for generating complex heatmaps in a procedure way.

Preparation

package can be installed from

library(devtools)
install_github('zwdzwd/wheatmap')

We start with some data

library(wheatmap)
m <- cbind(matrix(rnorm(20),nrow=4), 5+matrix(rnorm(8),nrow=4))
m2 <- matrix(1:16,nrow=4)
dimnames(m) <- list(c('w','x','y','z'), c('a','b','c','d','e','f','g'))
row.data <- c(1,2,3,1)
col.data <- c(1:6,6)
m[,1:4]
##            a           b            c          d
## w -0.8388943 -0.62775638  0.001361459 -1.0277158
## x -0.5613855  0.02641383 -1.253562763  0.3064911
## y -0.2259031 -0.51624689  0.881087524 -0.8960159
## z -0.4966423  1.71559564 -1.014296057  1.1532142

We perform some clustering. Note that cc$mat is the matrix after clustering and keeps the row and column names so that one can use them for reordering other color bars. cc$row.clust$order and cc$column.clust$order also provide a integer reordering.

cc <- both.cluster(m)
row.data <- row.data[cc$row.clust$order]
col.data <- col.data[cc$column.clust$order]
cc$mat[,1:4]
##             b          d          e          a
## w -0.62775638 -1.0277158 -0.0605757 -0.8388943
## y -0.51624689 -0.8960159  1.4357444 -0.2259031
## x  0.02641383  0.3064911 -1.8999765 -0.5613855
## z  1.71559564  1.1532142  0.6191278 -0.4966423

Final results

The end result of our tutorial can be done by the “one”-liner

WHeatmap(cc$mat, name='h1') +
  WColorBarV(row.data, LeftOf('h1'), 'c1') +
  WColorBarH(col.data, TopOf('h1'), 'c2') +
  WDendrogram(cc$row.clust, LeftOf('c1'), facing='right') +
  WDendrogram(cc$column.clust, TopOf('c2'), facing='bottom') +
  WColorBarV(1:4, RightOf('h1'), 'c3', continuous=TRUE) +
  WHeatmap(m2, RightOf('c3'), 'h2') +
  WColorBarH(rep(c(1,2,3),each=4), 
             Beneath(WColumnBind('h1', 'c3', 'h2')), 'c4', 
             cmp=CMPar(brewer.name='Set2'), continuous=FALSE) +
  WHeatmap(matrix(rep(c(8:1,1:8),4),nrow=4), 
           Beneath('c4', h.aln=WColumnBind('h1','c3')), 'h3') +
  WHeatmap(matrix(rep(1:10),ncol=2),LeftOf(WRowBind('c4.1.1','h3.1.1'))) +
  WHeatmap(matrix(1:4,nrow=2), RightOf('h3', h.scale='h2'), 'h4') +
  WHeatmap(matrix(1:24,nrow=3), Beneath('h3'), 'h5') +
  WHeatmap(matrix(24:1,nrow=2), 
           Beneath('h5', h.aln=WColumnBind('h1','c3','h2')), 'h6') +
  WLegendV('c1', BottomRightOf('h6.1.3', h.pad=0.01), 'l1') +
  WLegendV('c2', TopOf('l1', pad = 0.1), 'l2') +
  WLegendV('c3', RightOf('l1', pad=0.1), 'l3', n.text=3, label.fontsize = 10) + 
  WLabel('Rainbow colors', RightOf('l2', pad=0.08), rot=-90) +
  WLabel('a little\nhouse', color='black', 
         WPosition(1,2,'h4',data.coord=TRUE, just=c('center','center'))) + 
  WRect('h3.1.1', c(2,5),c(2,3),col='yellow') +
  WRect('h1',c(5,6),c(2,3),col='yellow')

Step by step construction

We plot one heatmap first

a <- WHeatmap(cc$mat, name='h1')
a

Then we add top and left color bars

a <- a + WColorBarV(row.data, LeftOf('h1'), 'c1')
a <- a + WColorBarH(col.data, TopOf('h1'), 'c2')
a

Then the dendrograms

a <- a + WDendrogram(cc$row.clust, LeftOf('c1'), facing='right')
a <- a + WDendrogram(cc$column.clust, TopOf('c2'), facing='bottom')
a

Then another vertical color bar on the right. This one we want to have a continuous scale. Then another heatmap on the further right.

a <- a + WColorBarV(1:4, RightOf('h1'), 'c3', continuous=TRUE)
a <- a + WHeatmap(m2, RightOf('c3'), 'h2')
a

Now we can merge 3 items we plot and add a horizontal bar below. Note wheatmap automatically computes the split for you. It’s the users’ responsibility however, to make sure data are alignable.

a <- a + WColorBarH(rep(c(1,2,3),each=4), 
                    Beneath(WColumnBind('h1', 'c3', 'h2')), 'c4', 
                    cmp=CMPar(brewer.name='Set2'), continuous=FALSE)
a

We then add another matrix that span two objects under c4. And a vertial 2-column heatmap on the left that span 2 elements.

a <- a + WHeatmap(
  matrix(rep(c(8:1,1:8),4),nrow=4), 
  Beneath('c4', h.aln=WColumnBind('h1','c3')), 'h3')
a <- a + WHeatmap(matrix(rep(1:10),ncol=2),
                  LeftOf(WRowBind('c4.1.1','h3.1.1')))
a