pheatmap annotation - legend only for columns
1
3
Entering edit mode
5.4 years ago

I'm using the pheatmap package in R to cluster and visualize data. I have both column and row annotations. I would like to display the legend only for the row annotations and some of the column annotations. Is this possible?

annotation_legend only allows for TRUE or FALSE, however I would need something like annotation_legend_row.

Thanks!

R pheatmap • 35k views
ADD COMMENT
9
Entering edit mode
5.4 years ago

This? - here I add everything but then hide the row annotation colour bar by setting it to white.

Create random data

data <- replicate(20, rnorm(50))
rownames(data) <- paste("Gene", c(1:nrow(data)))
colnames(data) <- paste("Sample", c(1:ncol(data)))

Create col and row metadata

metadata <- data.frame(
      c(rep("case", ncol(data)/2), rep("control", ncol(data)/2)),
      c(rep("cond1", ncol(data)/4), rep("cond2", ncol(data)/4), rep("cond3", ncol(data)/4), rep("cond4", ncol(data)/4)),
      row.names=colnames(data))
colnames(metadata) <- c("casecontrol","condition")

metadata_gene <- data.frame(
      c(rep("Tcell", nrow(data)/2), rep("Bcell", nrow(data)/2)),
      row.names=rownames(data))
colnames(metadata_gene) <- c("Cell")

create the heatmap

require(pheatmap)
out <- pheatmap(data, 
      show_rownames=F, cluster_cols=T, cluster_rows=T, scale="row",
      cex=1, clustering_distance_rows="euclidean", cex=1,
      clustering_distance_cols="euclidean", clustering_method="complete", border_color=FALSE,
      annotation_col=metadata,
      annotation_row=metadata_gene)

a

modify the row annotation

library(grid)
grid.ls(grid.force())
grid.gedit("row_annotation", gp = gpar(col = "white", fill = "white", text = ""))

b

ADD COMMENT
0
Entering edit mode

Thanks, Kevin, but this is not what I was looking for. The annotation works just fine. I want the legend (on the right of the heatmap) to only be displayed for certain column annotations , in your case for instance only for condition but not for case control - or no legend for column annotations, just for row annotations would be OK too. Any ideas?

ADD REPLY
0
Entering edit mode

I see! - we can still use the same idea, though.

When you run the grid.ls(grid.force()) command, you'll see a list appear:

layout
  col_tree.2-3-2-3
  row_tree.4-1-4-1
  matrix.4-3-4-3
    GRID.rect.36
  col_names.5-3-5-3
  col_annotation.3-3-3-3
  col_annotation_names.3-4-3-4
  row_annotation.4-2-4-2
  row_annotation_names.5-2-5-2
  annotation_legend.4-6-5-6
    GRID.text.44
    GRID.rect.45
    GRID.text.46
    GRID.text.47
    GRID.rect.48
    GRID.text.49
    GRID.text.50
    GRID.rect.51
    GRID.text.52
  legend.4-5-5-5
    GRID.rect.54
    GRID.text.55

These are objects / components in the plot. We can edit these in the same way that I mentioned previously. The row colour bar is stored as row_annotation.4-2-4-2; our annotation legends are listed under annotation_legend.4-6-5-6; the vertical colour key components are listed under legend.4-5-5-5.

Here is a reproducible answer to get rid of all components of the condition legend, and just the title of the cell legend:

Create random data

data <- replicate(20, rnorm(50))
rownames(data) <- paste("Gene", c(1:nrow(data)))
colnames(data) <- paste("Sample", c(1:ncol(data)))

Create col and row metadata

metadata <- data.frame(
      c(rep("case", ncol(data)/2), rep("control", ncol(data)/2)),
      c(rep("cond1", ncol(data)/4), rep("cond2", ncol(data)/4), rep("cond3", ncol(data)/4), rep("cond4", ncol(data)/4)),
      row.names=colnames(data))
colnames(metadata) <- c("casecontrol","condition")

metadata_gene <- data.frame(
      c(rep("Tcell", nrow(data)/2), rep("Bcell", nrow(data)/2)),
      row.names=rownames(data))
colnames(metadata_gene) <- c("Cell")

create the heatmap

require(pheatmap)
out <- pheatmap(data, 
      show_rownames=F, cluster_cols=T, cluster_rows=T, scale="row",
      cex=1, clustering_distance_rows="euclidean", cex=1,
      clustering_distance_cols="euclidean", clustering_method="complete", border_color=FALSE,
      annotation_col=metadata,
      annotation_row=metadata_gene)

a

identify the objects in the plot

library(grid)
grid.ls(grid.force())

edit the objects

# `condition`
grid.gedit("GRID.text.44", gp = gpar(col="white"))
grid.gedit("GRID.rect.45", gp = gpar(fill="white"))
grid.gedit("GRID.text.46", gp = gpar(col="white"))

# `cell`
grid.gedit("GRID.text.50", gp = gpar(col="white"))

b

ADD REPLY
0
Entering edit mode

Thank you very much for the thorough explanation! Unfortunately this still doesn't quite solve my issue. As I have a multitude of annotations, pheatmap cuts any legend that exceeds the height of the image. I don't want to make the image height big enough to display all legend entries. As some of my legend entries share the same color code it would be better to not show them. I was hoping that I could delete some legend entries and then the later entries would move into their space. Your solution introduces white space instead and the later legend entries are still not visible. Do you know how I can manually reorder the legend entries? So that in your example case control would be plotted before condition? That would be great! Thanks a lot!

ADD REPLY
0
Entering edit mode

Yes, you can just flip them by manually ordering like this:

require(pheatmap)
out <- pheatmap(data, 
      show_rownames=F, cluster_cols=T, cluster_rows=T, scale="row",
      cex=1, clustering_distance_rows="euclidean", cex=1,
      clustering_distance_cols="euclidean", clustering_method="complete", border_color=FALSE,
      annotation_col=metadata[,c("condition","casecontrol")],
      annotation_row=metadata_gene)

That should flip condition with casecontrol.

If you have issues fitting the legends on the plot, then also consider modifying the width and height via the width and height parameters, passed to either or both of pheatmap() when you generate the plot and to pdf() when you save it.

ADD REPLY
0
Entering edit mode

if I understand it well that flips the annotation both in the annotation and the legend? I would like to only flip it in the legend - is that possible?

ADD REPLY
1
Entering edit mode

Although I am sure that there are ways to do that via coding, the quickest way is likely in a graphics editor, i.e., after you have generated and saved the figure to disk. Also, ComplexHeatmap provides much more flexibility than pheatmap for these things. I always use ComplexHeatmap. Working with the gplots and pheatmap heatmaps can be frustrating due to this lack of flexibility.

ADD REPLY
1
Entering edit mode

ah that's too bad, but thank you very much for your help! especially the grid package made me understand the heatmap better. thanks!

ADD REPLY

Login before adding your answer.

Traffic: 2018 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