The ggalign
package
offers several align_*
functions that allow you to
precisely control plot layout and integrate additional plots. Currently,
there are two primary align_*
functions for adding
plots:
align_gg()
/ggalign()
: Create ggplot object
with a customized data.align_panel()
/ggpanel()
: Create ggplot
object with the layout panel data.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)))
align_gg
align_gg()
is similar to ggplot
in that it
initializes a ggplot
data and mapping
. Same
with other align_*
functions. align_gg()
allowing you to provide data in various formats, including matrices,
data frames, or simple vectors. This data can be also inherited from the
layout.
align_gg()
always applies a default mapping for the axis
of the data index in the layout. This mapping is
aes(y = .data$.y)
for horizontal stacking (including left
and right heatmap annotation) and aes(x = .data$.x)
for
vertical stacking (including top and bottom heatmap annotation). For
more information, refer to the “ggplot2 Specification” section in the
align_gg()
documentation.
You can also use the ggalign()
function, which is an
alias for align_gg()
.
ggheatmap(small_mat) +
scale_fill_viridis_c(guide = "none") +
hmanno("t") +
ggalign(data = rowSums) +
geom_point(aes(y = value))
#> → heatmap built with `geom_tile()`
align_gg()
/ggalign()
requires the specific
data format for its operations. If you need to transform or filter data
for individual geoms
, you can use the data
argument within each geom
. However, if you have multiple
geoms
and want a consistent transformation applied across
all, you can utilize the plot action argument data
in the
align_gg()
/ggalign()
function. This allows you
to transform the default data for all subsequent geoms.
set.seed(1234L)
ggheatmap(small_mat) +
scale_fill_viridis_c(guide = "none") +
hmanno("t") +
align_kmeans(3L) +
ggalign(action = plot_action(data = function(data) subset(data, .panel == 1L))) +
geom_bar(aes(y = value, fill = .row_names), stat = "identity")
#> → heatmap built with `geom_tile()`
If the action data function has been set in both the single plot and
the parent layout, Whether the action data function is applied after the
parent layout’s action data depends on the inherit
argument
in plot_action()
. By default, this argument is set to
FALSE
, meaning that the action data function will not apply
the transformations from the parent layout.
The following plot will result in an empty plot area since no data remains after filtering:
set.seed(1234L)
ggheatmap(small_mat) +
scale_fill_viridis_c(guide = "none") +
hmanno("t",
action = plot_action(data = function(data) subset(data, .panel == 1L))
) +
align_kmeans(3L) +
# this action data function will be applied after the layout action data
# function, so there is no panel in `2`
ggalign(action = plot_action(
data = function(data) subset(data, .panel == 2L),
inherit = TRUE
)) +
geom_bar(aes(y = value, fill = .row_names), stat = "identity")
#> → heatmap built with `geom_tile()`
To resolve this issue, you can set inherit = FALSE
, or
keep the default value:
set.seed(1234L)
ggheatmap(small_mat) +
scale_fill_viridis_c(guide = "none") +
hmanno("t",
action = plot_action(data = function(data) subset(data, .panel == 1L))
) +
align_kmeans(3L) +
# this action data function will be applied after the layout action data
# function
ggalign(
action = plot_action(
data = function(data) subset(data, .panel == 2L),
inherit = FALSE
)
) +
geom_bar(aes(y = value, fill = .row_names), stat = "identity")
#> → heatmap built with `geom_tile()`
This functionality is particularly useful for
ggoncoplot()
, as it relies on action data to prepare the
data internally.
When used in a heatmap layout, and the data is inherited from the
heatmap data, a special column .extra_panel
will be added,
which is the panel information for column (left or right annotation) or
row (top or bottom annotation). This is useful if you want to create
summary plot using another axis panel. In such cases, it’s often
necessary to disable the automatic setting of limits
(limits = FALSE
in align_gg()
).
set.seed(1L)
v <- stats::rnorm(50L)
split <- sample(letters[1:2], 50L, replace = TRUE)
ggheatmap(v) +
scale_fill_viridis_c() +
theme(strip.text = element_text(), strip.background = element_rect()) +
hmanno("r") +
align_group(split) +
hmanno("t", size = 0.5) +
ggalign(limits = FALSE) +
geom_boxplot(aes(.extra_panel, value, fill = .extra_panel),
# here, we use `print()` to show the underlying data
data = function(data) {
print(head(data))
data
}
) +
scale_fill_brewer(palette = "Dark2", name = "branch")
#> → heatmap built with `geom_tile()`
#> .row_index .column_index value .extra_panel .panel .x
#> 1 1 1 -0.6264538 b 1 1
#> 2 1 2 0.1836433 b 1 1
#> 3 1 3 -0.8356286 b 1 1
#> 4 1 4 1.5952808 a 1 1
#> 5 1 5 0.3295078 a 1 1
#> 6 1 6 -0.8204684 a 1 1
This approach replicates the functionality of ComplexHeatmap::anno_summary(), but is versatile enough to be used with any heatmap, not just single-column or single-row heatmaps.
ggheatmap(small_mat) +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("t") +
align_dendro(aes(color = branch), k = 3L) +
scale_color_brewer(palette = "Dark2") +
hmanno("r", size = 0.5) +
ggalign(limits = FALSE) +
geom_boxplot(aes(y = .extra_panel, x = value, fill = factor(.extra_panel))) +
scale_fill_brewer(palette = "Dark2", name = "branch")
#> → heatmap built with `geom_tile()`
ggplot2
only allow add titles in the top or add caption
in the bottom. The ggalign package extends this capability, allowing you
to place titles around any border of the plot using the
patch_titles()
function.
ggheatmap(small_mat) +
patch_titles(left = "left patch title", bottom = "bottom patch title") +
theme(axis.text.x = element_text(angle = -60, hjust = 0)) +
hmanno("t") +
align_dendro(aes(color = branch), k = 3L) +
scale_color_brewer(palette = "Dark2") +
patch_titles(top = "top patch title") +
hmanno("r", size = 0.5) +
ggalign(limits = FALSE) +
geom_boxplot(aes(y = .extra_panel, x = value, fill = factor(.extra_panel))) +
scale_fill_brewer(palette = "Dark2", name = "branch") +
patch_titles(right = "right patch title")
#> → heatmap built with `geom_tile()`
align_panel
The align_panel()
function is similar to align_gg(), but
it operates specifically with layout panel data, removing all axis
labels and ticks. The ggpanel()
function is an alias for
align_panel()
.
The data in the underlying ggplot
object contains
following columns:
.panel
: the panel for current layout axis..index
: the index of the original layout data..x
or .y
: the x
or
y
coordinatesYou can use align_panel()
to integrate additional
elements, such as block annotation or customized panel title, into your
layout.
ggheatmap(small_mat) +
hmanno("t", size = unit(1, "cm")) +
align_kmeans(centers = 3L) +
ggpanel() +
geom_tile(aes(y = 1L, fill = .panel, color = .panel),
width = 1L, height = 1L
) +
geom_text(aes(y = 1L, label = .panel),
data = function(data) {
aggregate(.x ~ .panel, data, FUN = median)
}
)
#> → heatmap built with `geom_tile()`
sessionInfo()
#> R version 4.4.1 (2024-06-14)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.1 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.26.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=C
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] bookdown_0.41 ggalign_0.0.4.9000 ggplot2_3.5.1 rmarkdown_2.28
#>
#> loaded via a namespace (and not attached):
#> [1] gtable_0.3.5 jsonlite_1.8.9 compiler_4.4.1 highr_0.11
#> [5] crayon_1.5.3 ggbeeswarm_0.7.2 jquerylib_0.1.4 textshaping_0.4.0
#> [9] systemfonts_1.1.0 scales_1.3.0 yaml_2.3.10 fastmap_1.2.0
#> [13] R6_2.5.1 labeling_0.4.3 knitr_1.48 tibble_3.2.1
#> [17] maketools_1.3.1 munsell_0.5.1 bslib_0.8.0 pillar_1.9.0
#> [21] RColorBrewer_1.1-3 rlang_1.1.4 utf8_1.2.4 cachem_1.1.0
#> [25] xfun_0.48 sass_0.4.9 sys_3.4.3 viridisLite_0.4.2
#> [29] cli_3.6.3 withr_3.0.1 magrittr_2.0.3 digest_0.6.37
#> [33] grid_4.4.1 beeswarm_0.4.0 lifecycle_1.0.4 vipor_0.4.7
#> [37] ggrastr_1.0.2 vctrs_0.6.5 evaluate_1.0.1 glue_1.8.0
#> [41] farver_2.1.2 ragg_1.3.3 buildtools_1.0.0 fansi_1.0.6
#> [45] colorspace_2.1-1 tools_4.4.1 pkgconfig_2.0.3 htmltools_0.5.8.1