Tool:Grammar of Graphics for Heatmap
0
1
Entering edit mode
3 months ago
Yun ▴ 50

Hi, I have developed a package called ggalign. This package extends ggplot2 by providing advanced tools for aligning and organizing multiple plots, particularly those that automatically reorder observations, such as dendrogram. It offers fine control over layout adjustment and plot annotations, enabling you to create complex, publication-quality visualizations while still using the familiar grammar of ggplot2.

Why use ggalign?

ggalign focuses on aligning observations across multiple plots. It leverages the "number of observations" in the vctrs package or NROW() function to maintain consistency in plot organization.

If you've ever struggled with aligning plots with self-contained ordering (like dendrogram), or applying consistent grouping or ordering across multiple plots (e.g., with k-means clustering), ggalign is designed to make this easier. The package integrates seamlessly with ggplot2, providing the flexibility to use its geoms, scales, and other components for complex visualizations.

Installation

You can install ggalign from CRAN using:

install.packages("ggalign")

The latest version has modified a lot, try to use the development version now.

Alternatively, install the development version from GitHub with:

# install.packages("remotes")
remotes::install_github("Yunuuuu/ggalign")

Getting Started

The usage of ggalign is simple if you're familiar with ggplot2 syntax, ggalign works with a simple workflow:

  • Initialize the layout using ggheatmap() or ggstack().
  • Customize the layout with:
    • align_group(): Group layout axis into panel with a group variable.
    • align_kmeans(): Group layout axis into panel by kmeans
    • align_reorder(): Reorder layout observations based on statistical weights or allows for manual reordering based on user-defined criteria.
    • align_dendro(): Reorder or Group layout based on hierarchical clustering
  • Adding plots with ggalign() or ggpanel(), then add ggplot2 elements like geoms, stats, scales.

Basic example

Below, we'll walk through a basic example of using ggalign to create a heatmap with a dendrogram.

library(ggalign)
set.seed(123)
small_mat <- matrix(rnorm(81), nrow = 9)
rownames(small_mat) <- paste0("row", seq_len(nrow(small_mat)))
colnames(small_mat) <- paste0("column", seq_len(ncol(small_mat)))

# initialize the heatmap layout, we can regard it as a normal ggplot object
ggheatmap(small_mat) + 
    # we can directly modify geoms, scales and other ggplot2 components
    scale_fill_viridis_c() +
    # add annotation in the top
    hmanno("top") +
    # in the top annotation, we add a dendrogram, and split observations into 3 groups
    align_dendro(aes(color = branch), k = 3) +
    # in the dendrogram we add a point geom
    geom_point(aes(color = branch, y = y)) +
    # change color mapping for the dendrogram
    scale_color_brewer(palette = "Dark2")

Compare with other ggplot2 heatmap extension

The main advantage of ggalign over other extensions like ggheatmap is its full compatibility with the ggplot2 grammar. You can seamlessly use any ggplot2 geoms, stats, and scales to build complex layouts, including multiple heatmaps arranged vertically or horizontally.

Compare with ComplexHeatmap

Pros

  • Full integration with the ggplot2 ecosystem.
  • Heatmap annotation axes and legends are automatically generated.
  • Dendrogram can be easily customized and colored.
  • Flexible control over plot size and spacing.
  • Can easily align with other ggplot2 plots by panel area.

Cons

Fewer Built-In Annotations: May require additional coding for specific annotations or customization compared to the extensive built-in annotation function in ComplexHeatmap.

More Complex Examples

Here are some more advanced visualizations using ggalign:

ggplot2 heatmap • 736 views
ADD COMMENT
0
Entering edit mode

Welcom feature request and issues

ADD REPLY
0
Entering edit mode

If you can get it to play nicely with plotly's ggplotly() function, that'd be pretty neato.

ADD REPLY
0
Entering edit mode

Sorry, the internal will build a patchwork firstly, but plotly doesn't support the patchwork. So it's not possible for this to work with ggplotly. Please see https://github.com/plotly/plotly.R/issues/2028 for details

ADD REPLY
0
Entering edit mode

Can you plot faceted heat maps with this? i.e. If I create n heat maps... I can use do.call/grid.arrange to plot them all on 1 image, but it is awkward, and I still can't figure out how to add a main title, you need R(KungFuSkills) for that.

ADD REPLY
1
Entering edit mode

Yes, it internally use facet to plot the heatmap groups. The dendrogram will be aligned well with any ggplot objects (Just use the ggalign function to create a ggplot plot) in the facet layout.

I have changed the default theme, and it can support connect multiple heatmap horizontally or vertically.

Because it can now align a dendrogram in a standard ggplot2 plot, enhancing its versatility, and it has been renamed into ggalign:

mat <- matrix(rnorm(81), nrow = 9)
rownames(mat) <- paste0("row", seq_len(nrow(mat)))
colnames(mat) <- paste0("column", seq_len(ncol(mat)))
ggheatmap(mat) +
  scale_fill_viridis_c() +
  hmanno("t") +
  align_dendro(aes(color = branch), k = 3L) +
  ggalign(aes(y = value), data = rowSums) +
  geom_bar(stat = "identity", aes(fill = factor(.panel))) +
  scale_fill_brewer(name = NULL, palette = "Dark2") +
  hmanno("l") +
  ggalign(aes(x = value), data = rowSums, size = 0.5) +
  geom_bar(
    aes(y = .y, fill = factor(.y)),
    stat = "identity",
    orientation = "y"
  ) +
  scale_x_reverse() +
  align_dendro(aes(color = branch),
    size = unit(1, "null"),
    k = 4L
  ) +
  scale_x_reverse()

Created on 2024-07-17 with [reprex v2.1.0](https://reprex.tidyverse.org) ~
enter image description here

layout_stack put plots horizontally or vertically. You can also use the alias ggstack.

set.seed(123)
mat1 <- matrix(rnorm(80, 2), 8, 10)
mat1 <- rbind(mat1, matrix(rnorm(40, -2), 4, 10))
rownames(mat1) <- paste0("R", 1:12)
colnames(mat1) <- paste0("C", 1:10)

mat2 <- matrix(runif(60, max = 3, min = 1), 6, 10)
mat2 <- rbind(mat2, matrix(runif(60, max = 2, min = 0), 6, 10))
rownames(mat2) <- paste0("R", 1:12)
colnames(mat2) <- paste0("C", 1:10)

le <- sample(letters[1:3], 12, replace = TRUE)
names(le) <- paste0("R", 1:12)

ind <- sample(12, 12)
mat1 <- mat1[ind, ]
mat2 <- mat2[ind, ]
le <- le[ind]
ht1 <- ggheatmap(mat1, width = 1) +
  scale_fill_viridis_c() +
  hmanno("t") +
  align_dendro(k = 3L) +
  scale_y_continuous(expand = expansion()) +
  hmanno(NULL)
ht2 <- ggheatmap(mat2, width = 1)
ggstack(mat1, rel_sizes = c(0.2, 1, 1)) +
  align_dendro(size = 0.2) +
  scale_x_reverse() +
  ht1 +
  ht2 +
  ggalign(data = le, size = 0.2) +
  geom_tile(aes(x = .column_index, fill = value)) +
  scale_x_continuous(name = NULL, labels = NULL, breaks = NULL) &
  theme(plot.margin = margin())

enter image description here

ADD REPLY

Login before adding your answer.

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