In this thread, We’ll use ggalign
to draw all the
heatmap in https://jokergoo.github.io/ComplexHeatmap-reference/book/a-single-heatmap.html
set.seed(123)
nr1 <- 4
nr2 <- 8
nr3 <- 6
nr <- nr1 + nr2 + nr3
nc1 <- 6
nc2 <- 8
nc3 <- 10
nc <- nc1 + nc2 + nc3
mat <- cbind(
rbind(
matrix(rnorm(nr1 * nc1, mean = 1, sd = 0.5), nrow = nr1),
matrix(rnorm(nr2 * nc1, mean = 0, sd = 0.5), nrow = nr2),
matrix(rnorm(nr3 * nc1, mean = 0, sd = 0.5), nrow = nr3)
),
rbind(
matrix(rnorm(nr1 * nc2, mean = 0, sd = 0.5), nrow = nr1),
matrix(rnorm(nr2 * nc2, mean = 1, sd = 0.5), nrow = nr2),
matrix(rnorm(nr3 * nc2, mean = 0, sd = 0.5), nrow = nr3)
),
rbind(
matrix(rnorm(nr1 * nc3, mean = 0.5, sd = 0.5), nrow = nr1),
matrix(rnorm(nr2 * nc3, mean = 0.5, sd = 0.5), nrow = nr2),
matrix(rnorm(nr3 * nc3, mean = 1, sd = 0.5), nrow = nr3)
)
)
mat <- mat[sample(nr, nr), sample(nc, nc)]
rownames(mat) <- paste0("row", seq_len(nr))
colnames(mat) <- paste0("column", seq_len(nc))
Colors
Because the ComplexHeatmap
will reorder the dendrogram
by default, but align_dendro
won’t change the tree layout.
In following codes, we hypothesized that the arguments
row_dend_reorder
and column_dend_reorder
of
ComplexHeatmap::Heatmap
is FALSE
.
It is important to note that ggalign
considers the
left-bottom as the starting point, while ComplexHeatmap
considers the left-top as the starting point.
The scale_fill_*
function in ggplot2 makes it easy to
modify colors.
dim(mat)
#> [1] 18 24
ggheatmap(mat) +
scale_fill_gradient2(low = "#2600D1FF", high = "#EE3F3FFF") +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
# ComplexHeatmap::Heatmap(mat,
# row_dend_reorder = FALSE,
# column_dend_reorder = FALSE
# )
ggheatmap(mat) +
scale_fill_gradient2(low = "green", high = "red") +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
oob
argument in the scale_fill_*
function
can be used to deal with the outliers.
mat2 <- mat
mat2[1, 1] <- 100000
ggheatmap(mat2) +
scale_fill_gradient2(
low = "green", high = "red",
limits = c(-2, 2),
oob = scales::squish
) +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
We can use align_plots()
to arrange them.
h1 <- ggheatmap(mat) +
scale_fill_gradient2(name = "mat", low = "green", high = "red") +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
h2 <- ggheatmap(mat / 4) +
scale_fill_gradient2(
name = "mat/4", limits = c(-2, 2L),
oob = scales::squish,
low = "green", high = "red"
) +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
h3 <- ggheatmap(abs(mat)) +
scale_fill_gradient2(name = "abs(mat)", low = "green", high = "red") +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
align_plots(h1, h2, h3, ncol = 2L)
ggheatmap(mat) +
scale_fill_gradientn(colors = rev(rainbow(10))) +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
For character matrix, you can use ggplot2 discrete filling scales.
discrete_mat <- matrix(sample(1:4, 100, replace = TRUE), 10, 10)
colors <- structure(1:4, names = c("1", "2", "3", "4")) # black, red, green, blue
ggheatmap(discrete_mat, aes(fill = factor(value))) +
scale_fill_manual(values = colors) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
discrete_mat <- matrix(sample(letters[1:4], 100, replace = TRUE), 10, 10)
colors <- structure(1:4, names = letters[1:4])
ggheatmap(discrete_mat) +
scale_fill_manual(values = colors)
mat_with_na <- mat
na_index <- sample(c(TRUE, FALSE),
nrow(mat) * ncol(mat),
replace = TRUE, prob = c(1, 9)
)
mat_with_na[na_index] <- NA
ggheatmap(mat_with_na) +
scale_fill_gradient2(
low = "#2600D1FF",
high = "#EE3F3FFF",
na.value = "black"
) +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
We won’t compare the LAB and RGB space. If you want to convert color between different color space, try to use farver pacakge.
In ggplot2, you can use panel.border
argument in
theme()
function to control the Heatmap body border.
ggheatmap(mat) +
scale_fill_gradient2(low = "#2600D1FF", high = "#EE3F3FFF") +
theme(
axis.text.x = element_text(angle = -60, hjust = 0),
panel.border = element_rect(linetype = "dashed", fill = NA)
) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
You can use color
aesthetic to specify the cell border
color and linewidth
aesthetic to specify the border
width.
ggheatmap(mat, color = "white") +
scale_fill_gradient2(low = "#2600D1FF", high = "#EE3F3FFF") +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
You can use filling
argument to turn off the heatmap
cell filling.
ggheatmap(mat, filling = FALSE) +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(15, "mm")) +
align_dendro() +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
hmanno(NULL) &
theme(plot.margin = margin())
Titles
We can use patch_titles()
to add titles around each
border of the plot. You can use theme()
to control the text
appearance.
ggheatmap(mat) +
scale_fill_gradient2(low = "#2600D1FF", high = "#EE3F3FFF") +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(20, "mm")) +
align_dendro() +
patch_titles(right = "I am a row title") +
theme(plot.patch_title.right = element_text(face = "bold", size = 16)) +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
patch_titles(top = "I am a column title") +
theme(plot.patch_title.top = element_text(face = "bold", size = 16)) +
hmanno(NULL) &
theme(plot.margin = margin())
Clustering
ggheatmap(mat) +
scale_fill_gradient2(low = "#2600D1FF", high = "#EE3F3FFF") +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("r", size = unit(20, "mm")) +
align_dendro(distance = "pearson") +
theme(plot.patch_title.right = element_text(face = "bold", size = 16)) +
hmanno("t", size = unit(15, "mm")) +
align_dendro() +
patch_titles(top = "pre-defined distance method (1 - pearson)") +
theme(plot.patch_title.top = element_text(face = "bold", size = 16)) +
hmanno(NULL) &
theme(plot.margin = margin())
# ComplexHeatmap::Heatmap(mat,
# name = "mat", clustering_distance_rows = "pearson",
# column_title = "pre-defined distance method (1 - pearson)",
# row_dend_reorder = FALSE,
# column_dend_reorder = FALSE
# )
Session information
sessionInfo()
#> R version 4.4.1 (2024-06-14)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 22.04.5 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so; LAPACK version 3.10.0
#>
#> locale:
#> [1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
#> [4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
#> [7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
#> [10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] ggalign_0.0.4 ggplot2_3.5.1
#>
#> loaded via a namespace (and not attached):
#> [1] gtable_0.3.5 jsonlite_1.8.8 highr_0.11 dplyr_1.1.4
#> [5] compiler_4.4.1 tidyselect_1.2.1 tidyr_1.3.1 jquerylib_0.1.4
#> [9] systemfonts_1.1.0 scales_1.3.0 textshaping_0.4.0 yaml_2.3.10
#> [13] fastmap_1.2.0 R6_2.5.1 labeling_0.4.3 generics_0.1.3
#> [17] knitr_1.48 tibble_3.2.1 desc_1.4.3 munsell_0.5.1
#> [21] bslib_0.8.0 pillar_1.9.0 rlang_1.1.4 utf8_1.2.4
#> [25] cachem_1.1.0 xfun_0.47 fs_1.6.4 sass_0.4.9
#> [29] cli_3.6.3 pkgdown_2.1.1 withr_3.0.1 magrittr_2.0.3
#> [33] digest_0.6.37 grid_4.4.1 lifecycle_1.0.4 vctrs_0.6.5
#> [37] evaluate_1.0.0 glue_1.7.0 farver_2.1.2 ragg_1.3.3
#> [41] fansi_1.0.6 colorspace_2.1-1 rmarkdown_2.28 purrr_1.0.2
#> [45] tools_4.4.1 pkgconfig_2.0.3 htmltools_0.5.8.1