Adding column annotation to heatmap using Complexheatmap
1
2
Entering edit mode
6.5 years ago
Vasu ▴ 790

I have a matrix "data" like this

            Sample1 Sample2 Sample3 Sample4 Sample5 Sample6 Sample7
AC008870.3  1.0502  1.5076  1.3916  0.3655  1.1028  0.6700  1.6719
TLX1NB      2.0357  1.6799  -0.5898 -0.2286 1.8068  2.0801  2.1399
LINC00511   1.6435  1.3586  1.5394  1.0144  0.6329  1.6717  0.9201
PRC1-AS1    1.3657  1.5695  0.7393  0.8945  1.6971  0.7516  1.8048
AL161431.1  -0.6128 -0.6128 2.5562  -0.2102 -0.1496 -0.3387 -0.2035
AC022784.1  -1.0502 -0.1724 0.4127  2.3219  -0.6579 1.4954  -0.5929
LINC00518   -0.6053 -0.4479 -0.3621 0.0543  0.9048  0.1343  0.0658
C5orf66-AS1 0.2909  0.0603  0.3172  -0.3273 0.3660  -0.0113 -0.0723
AL589182.1  0.4675  1.9790  -0.6627 1.4468  0.4681  -0.6627 1.4636
LINC01705   1.8079  -0.1598 1.0448  0.0201  -0.0780 1.8574  1.0598
AC007639.1  1.8472  1.5940  1.6298  0.7072  0.8901  1.4685  0.8939
AL139099.5  0.4277  0.2271  0.5286  1.4965  1.2302  0.9821  1.1370

And the column data is in a dataframe "df"

Samples Type Type2
Sample1 M   AT
Sample2 M   AT
Sample3 M   AT
Sample4 N   PT
Sample5 N   PT
Sample6 N   PT
Sample7 M   AT

I'm able to make a heatmap using complex heatmap package, but a bit confused in adding column annotation to the heatmap.

pdf("heatmap.pdf", width=7, height=6.5)
Heatmap(data, name = "expression",  col = greenred(75), 
                  show_row_names = FALSE, show_column_names = FALSE,cluster_rows = TRUE,
                   cluster_columns = TRUE,show_column_dend = TRUE,show_row_dend = TRUE,
  row_dend_reorder = TRUE,column_dend_reorder = TRUE,clustering_method_rows = "ward.D2",
                   clustering_method_columns = "ward.D2",width = unit(100, "mm"))
dev.off()

How to add column annotation to the heatmap? Any help is appreciated.

RNA-Seq r heatmap complexheatmap • 30k views
ADD COMMENT
8
Entering edit mode
6.5 years ago

Here's a quick example to get you started, with top and bottom col annotations. The general function for adding annotation in ComplexHeatmap is HeatmapAnnotation(), and one distinguishes between col and row annotation via the 'which' parameter, as you'll see below. It follow, then, that both row and col annotation are added differently to the heatmap object, as I show in my example here: C: how to cluster genes in heatmap

In short, col annotations are added via the top_annotation and bottom_annotation parameters passed to the Heatmap() function, whereas row annotations are added via the draw() function (as you'll see in my other example).

data
            Sample1 Sample2 Sample3 Sample4 Sample5 Sample6 Sample7
AC008870.3   1.0502  1.5076  1.3916  0.3655  1.1028  0.6700  1.6719
TLX1NB       2.0357  1.6799 -0.5898 -0.2286  1.8068  2.0801  2.1399
LINC00511    1.6435  1.3586  1.5394  1.0144  0.6329  1.6717  0.9201
PRC1-AS1     1.3657  1.5695  0.7393  0.8945  1.6971  0.7516  1.8048
AL161431.1  -0.6128 -0.6128  2.5562 -0.2102 -0.1496 -0.3387 -0.2035
AC022784.1  -1.0502 -0.1724  0.4127  2.3219 -0.6579  1.4954 -0.5929
LINC00518   -0.6053 -0.4479 -0.3621  0.0543  0.9048  0.1343  0.0658
C5orf66-AS1  0.2909  0.0603  0.3172 -0.3273  0.3660 -0.0113 -0.0723
AL589182.1   0.4675  1.9790 -0.6627  1.4468  0.4681 -0.6627  1.4636
LINC01705    1.8079 -0.1598  1.0448  0.0201 -0.0780  1.8574  1.0598
AC007639.1   1.8472  1.5940  1.6298  0.7072  0.8901  1.4685  0.8939
AL139099.5   0.4277  0.2271  0.5286  1.4965  1.2302  0.9821  1.1370

metadata
  Samples Type Type2
1 Sample1    M    AT
2 Sample2    M    AT
3 Sample3    M    AT
4 Sample4    N    PT
5 Sample5    N    PT
6 Sample6    N    PT
7 Sample7    M    AT

.

#Set annotation
ann <- data.frame(metadata$Type, metadata$Type2)
colnames(ann) <- c('Type', 'Type2')
colours <- list('Type' = c('M' = 'red2', 'N' = 'royalblue'),
  'Type2' = c('AT' = 'limegreen', 'PT' = 'gold'))
colAnn <- HeatmapAnnotation(df = ann,
  which = 'col',
  col = colours,
  annotation_width = unit(c(1, 4), 'cm'),
  gap = unit(1, 'mm'))

boxplotCol <- HeatmapAnnotation(
  boxplot=anno_boxplot(data.matrix(data),
    border=TRUE,
    gp=gpar(fill="#CCCCCC"),
    pch=".",
    size=unit(2, "mm"),
    axis=TRUE,
    axis_side="left",
    axis_gp=gpar(fontsize=12)),
  annotation_width=unit(c(1, 5.0), "cm"),
  which="col")


hmap <- Heatmap(
  data,
  name = "expression",
  col = greenred(75), 
  show_row_names = FALSE,
  show_column_names = FALSE,
  cluster_rows = TRUE,
  cluster_columns = TRUE,
  show_column_dend = TRUE,
  show_row_dend = TRUE,
  row_dend_reorder = TRUE,
  column_dend_reorder = TRUE,
  clustering_method_rows = "ward.D2",
  clustering_method_columns = "ward.D2",
  width = unit(100, "mm"),

  top_annotation_height=unit(1.0,"cm"), top_annotation=colAnn,

  bottom_annotation_height=unit(3, "cm"), bottom_annotation=boxplotCol)

draw(hmap, heatmap_legend_side="left", annotation_legend_side="right")

a

ADD COMMENT
0
Entering edit mode

Thank you very much Kevin.

ADD REPLY
1
Entering edit mode

You are very welcome.

ADD REPLY
0
Entering edit mode

One question. How to adjust the expression color? On my plot 15,10 (red), 5 (black), 0,-5 (green) was displayed and the whole plot was in green color. May I know how to adjust that? Check this plot

matrix with values is logCPM. When I used heatmap.2 function it looks fine. But when I'm using complexheatmap the whole plot was in green color

ADD REPLY
3
Entering edit mode

Yes, your heatmap just looks a bit 'flat', which can frequently happen but which does not necessarily mean that your data is incorrect. In such situations, it can be a good idea to plot Z-scaled data, which means, for example, that a value of +2 represents 2 standard deviations (sdevs) above the mean, whereas, -2 represents 2 sdevs below the mean, et cetera.

You can also quite easily specify your own colour scheme via the colorRampPalette() and colorRamp2() functions (from circlize package). If you scale your own data, it's also a good idea to specify your own 'breaks', i.e., thresholds in your data that indicate where colour should change. Doing this can help to exaggerate, for example, lower values. One then supplies the colour scheme and the breaks to the col parameter of the Heatmap() function, like this: col=colorRamp2(myBreaks, myCol)

Here, I generate your same heatmap twice with a different colour scheme and breaks.

require(ComplexHeatmap)
require(circlize)

#Specify colours and breaks
myCol1 <- colorRampPalette(c("violet", "black", "springgreen"))(100)
myBreaks1 <- seq(-3, 3, length.out=100)
myCol2 <- colorRampPalette(c("white", "grey50", "black"))(100)
myBreaks2 <- seq(-1, 1, length.out=100)

#Scale data to Z-scores
heat <- t(scale(t(data)))

#Set annotation
ann <- data.frame(metadata$Type, metadata$Type2)
colnames(ann) <- c('Type', 'Type2')
colours <- list(
  'Type' = c('M' = 'red2', 'N' = 'royalblue'),
  'Type2' = c('AT' = 'limegreen', 'PT' = 'gold'))
colAnn <- HeatmapAnnotation(df = ann,
  which = 'col',
  col = colours,
  annotation_width = unit(c(1, 4), 'cm'),
  gap = unit(1, 'mm'))

#Add column boxplot
boxplotCol <- HeatmapAnnotation(
  boxplot = anno_boxplot(data.matrix(heat),
    border = TRUE,
    gp = gpar(fill = '#CCCCCC'),
    pch = '.',
    size = unit(2, 'mm'),
    axis = TRUE,
    axis_side = 'left',
    axis_gp = gpar(fontsize = 12)),
  annotation_width = unit(c(1, 5.0), 'cm'),
  which = 'col')

hmap1 <- Heatmap(heat,
  name = 'expression1',
   col = colorRamp2(myBreaks1, myCol1),
   show_row_names = FALSE,
   show_column_names = FALSE,
   cluster_rows = TRUE,
   cluster_columns = TRUE,
   show_column_dend = TRUE,
   show_row_dend = TRUE,
   row_dend_reorder = TRUE,
   column_dend_reorder = TRUE,
   clustering_method_rows = 'ward.D2',
   clustering_method_columns = 'ward.D2',
   width = unit(100, 'mm'),
   top_annotation_height = unit(1.0, 'cm'),
   top_annotation = colAnn,
   bottom_annotation_height = unit(3, 'cm'),
   bottom_annotation = boxplotCol)


hmap2 <- Heatmap(heat,
   name = 'expression2',
   col = colorRamp2(myBreaks2, myCol2),
   show_row_names = FALSE,
   show_column_names = FALSE,
   cluster_rows = TRUE,
   cluster_columns = TRUE,
   show_column_dend = TRUE,
   show_row_dend = TRUE,
   row_dend_reorder = TRUE,
   column_dend_reorder = TRUE,
   clustering_method_rows = 'ward.D2',
   clustering_method_columns = 'ward.D2',
   width = unit(100, 'mm'),
   top_annotation_height = unit(1.0, 'cm'),
   top_annotation = colAnn,
   bottom_annotation_height = unit(3, 'cm'),
   bottom_annotation = boxplotCol)

draw(hmap1 + hmap2,
  heatmap_legend_side = "left',
  annotation_legend_side = 'right')

s

ADD REPLY
0
Entering edit mode

Actually the matrix which I posted in my question was Z-scaled data only. From the logCPM mentioned in edgeR tutorial I used logCPM <- t(scale(t(logCPM))) and then used it for heatmap. I adjusted the expression with breaks and it looks fine. Thanks a lot again.

ADD REPLY
0
Entering edit mode

Sorry Kevin, if I have two time points of single cell RNA-seq data, in time point 1 cells can be clustered to 2 clusters, Lets say for example in time point 1, cell1, cell9, .. (99 cells) placed in sub cluster 1, cell4, cell12,,, (34 cells) in sub cluster 2. I have also 2 sub-clusters for time point 2. I have 200 genes. I want to heat map these 200 genes so columns have annotation for example time point 1-sub-cluster1, time point1-sub-cluster2, time point2-subcluster 1 and time point2-subcluster2 something like this picture

enter image description here

That each day has sub clusters a, b, c, ..

May you please help me

ADD REPLY
1
Entering edit mode

Hello, I would post this as a new Question. I am unavailable for a number of days.

ADD REPLY

Login before adding your answer.

Traffic: 1608 users visited in the last hour
Help About
FAQ
Access RSS
API
Stats

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.

Powered by the version 2.3.6