Complex Heatmap: Changing order of clusters
1
9
Entering edit mode
4.3 years ago
yomogy ▴ 100

I have a question about how to change order of clusters on heatmap. I tried to make heatmap using Complex Heatmap package and I made K-mean clusters. my code is below:

 HM <- Heatmap(matrix2, km = 4, show_row_names = FALSE, show_column_names = F, top_annotation = ha_column, cluster_columns = FALSE, show_heatmap_legend = T)
draw(HM, heatmap_legend_side = "right", show_annotation_legend = F)


I got this heatmap as below. https://ibb.co/jqGb77

In this example, I want to move cluster 2 to top, cluster 1 in 2nd top, cluster 3 on 3rd and cluster 4 on the bottom. How can I re-order the position of clusters ?

R heatmap • 15k views
0
Entering edit mode

For future reference: On ibb.co site scroll down and look for a tab that says Embed codes. Click on Embed codes. Copy the code in HTML full image box. Post that line into your post here to parse the image in automatically (like above).

0
Entering edit mode

Hi Kevin,

Thanks a lot for your post.

I am getting the following error, would you have an idea to fix it ?

> kclus <- kmeans(assay(ntd), 4)
> head(kclus$cluster, 50) > # Use the split parameter of Heatmap() in order to split the heatmap based on the k-means result: > split <- paste0("Cluster\n", kclus$cluster)
> default.hmap <- ComplexHeatmap::Heatmap(assay(ntd), split=split, cluster_row_slices = FALSE)
>
> # re-order the gene-to-cluster assignment as a factor to fix the order of the clusters
> split <- factor(paste0("Cluster\n", kclus$cluster), levels=c("Cluster\n2","Cluster\n1","Cluster\n3","Cluster\n4")) > reorder.hmap <- ComplexHeatmap::Heatmap(assay(ntd), split=split, cluster_row_slices = FALSE) > > # drawing both the default-ordered and then re-ordered > pushViewport(viewport(layout=grid.layout(nr=1, nc=2))) > > pushViewport(viewport(layout.pos.row=1, layout.pos.col=1)) > draw(default.hmap, newpage=FALSE) Error: node stack overflow Error during wrapup: node stack overflow > upViewport()  Thanks a lot ! ADD REPLY 0 Entering edit mode Please use ADD COMMENT/ADD REPLY when responding to existing posts to keep threads logically organized. SUBMIT ANSWER is for new answers to original question. ADD REPLY 0 Entering edit mode What is the size of the data-matrix that you are trying to plot? ADD REPLY 1 Entering edit mode You're right, adapting the size of the data-matrix was the key. Thanks a lot ! ADD REPLY 0 Entering edit mode @Kevin Blighe, I would like to add my questions here if possible? 1. How I could show those four clusters in a colors-a color bar for each cluster as indicated for the sample clustering on the top of this post. 2. Then, is it possible to extract the cluster genes(for example cluster 1 in the above heatmaps) by calling the color bar? Theoretically, I am asking more or less a WGCNA approach of color assignment for each cluster of genes and extracting the cluster genes based on their color assignment? Thank you! ADD REPLY 0 Entering edit mode Open a new post, and please leave the answer field for answers only. Thank you. ADD REPLY 12 Entering edit mode 4.3 years ago I'm a big fan of ComplexHeatmap and again kudos to the developer for making it such a flexible package. However, I'm not immediately aware of a function that does (directly) what you want. I would prefer to perform the k-means outside of the ComplexHeatmap package by just using kmeans(), and then manipulating the gene-to-cluster assignment vector in order to dictate the order of the clusters. Create some random data (20 genes x 20 samples): test <- matrix(rexp(400, rate=.3), ncol=20) rownames(test) <- paste(rep("Gene", nrow(test)), 1:nrow(test), sep="") colnames(test) <- paste(rep("Sample", ncol(test)), 1:ncol(test), sep="")  We then perform k-means with 4 centers and take a look at the gene-to-cluster assignment: kclus <- kmeans(test, 4) kclus$cluster
Gene1  Gene2  Gene3  Gene4  Gene5  Gene6  Gene7  Gene8  Gene9 Gene10 Gene11
3      3      2      1      2      1      3      1      2      1      4
Gene12 Gene13 Gene14 Gene15 Gene16 Gene17 Gene18 Gene19 Gene20
4      4      1      2      4      2      2      4      2


We then use the split parameter of Heatmap() in order to split the heatmap based on the k-means result:

split <- paste0("Cluster\n", kclus$cluster) default.hmap <- Heatmap(test, split=split, cluster_row_slices = FALSE)  As we want to fix the order of the clusters, we have to re-order the gene-to-cluster assignment as a factor: split <- factor(paste0("Cluster\n", kclus$cluster), levels=c("Cluster\n2","Cluster\n1","Cluster\n3","Cluster\n4"))
reorder.hmap <- Heatmap(test, split=split, cluster_row_slices = FALSE)


Then draw both the default-ordered and then re-ordered:

pushViewport(viewport(layout=grid.layout(nr=1, nc=2)))

pushViewport(viewport(layout.pos.row=1, layout.pos.col=1))
draw(default.hmap, newpage=FALSE)
upViewport()

pushViewport(viewport(layout.pos.row=1, layout.pos.col=2))
draw(reorder.hmap, newpage=FALSE)
upViewport()

upViewport()


1
Entering edit mode

Thanks Kevin, it works perfecctly!!

1
Entering edit mode

And thank you for the question - I will re-use this code myself some time!

1
Entering edit mode

Thanks Kevin, this is very useful code.

0
Entering edit mode

I just tried this code with R 3.6.1 and ComplexHeatmap 2.0.0 and this code no longer works. The two heatmaps are now identical. EDIT: in the code above you forgot to set cluster_row_slices = FALSE

1
Entering edit mode

Thank you for alerting me to this. The code that I originally posted worked just fine when I posted my answer, ~18 months ago. cluster_row_slices either did not exist as a parameter in ComplexHeatmap at that time, or it existed and its default value was different. So, I had no need to include it then.

I have now edited the code in my answer (above) and it works with the latest ComplexHeatmap version.

The developer of ComplexHeatmap modified quite a few parameters and general functionality of the package in the relatively recent version change from Bioconductor 3.8 to Bioconductor 3.9 (we are now on the verge of Bioconductor 3.10).