7 quad-layout
quad_layout()
arranges plots around the quad-sides of a main plot, aligning both horizontal and vertical axes, and can handle either discrete or continuous variables.
Code
library(ggalign)
set.seed(123)
<- matrix(rnorm(56), nrow = 7)
small_mat rownames(small_mat) <- paste0("row", seq_len(nrow(small_mat)))
colnames(small_mat) <- paste0("column", seq_len(ncol(small_mat)))
7.1 Introduction
Depending on whether you want to align discrete or continuous variables in the horizontal
and vertical
direction, there are four main types of quad_layout()
:
Alignment of Observations | horizontal | vertical | Data Format |
---|---|---|---|
quad_continuous() /ggside() |
continuous | continuous | data frame |
quad_layout(xlim = ...) |
discrete | continuous | matrix |
quad_layout(ylim = ...) |
continuous | discrete | matrix |
quad_discrete() /ggheatmap() |
discrete | discrete | matrix |
7.2 Annotations
Annotation is typically handled using a stack_layout()
. Depending on whether you want to align observations in the specified direction, different stack_layout()
are compatible (Section 3.5). Below is a table outlining the compatibility of various layout types for annotations:
Annotations | left and right | top and bottom |
---|---|---|
quad_continuous() /ggside() |
stack_continuous() |
stack_continuous() |
quad_layout(xlim = ...) |
stack_discrete() |
stack_continuous() |
quad_layout(ylim = ...) |
stack_continuous() |
stack_discrete() |
quad_discrete() /ggheatmap() |
stack_discrete() |
stack_discrete() |
7.3 quad_discrete()
quad_discrete()
aligns discrete variables in both horizontal and vertical directions. It serves as the base version of ggheatmap()
/heatmap_layout()
and does not automatically add default layers or mappings.
The underlying ggplot
data of the main plot is the same with ggheatmap()
/heatmap_layout()
(Section 3.2), it is recommended to use .y
, or .discrete_y
as the y
mapping and use .x
or .discrete_x
as the x
mapping in the main plot.
quad_discrete(small_mat, aes(.x, .y)) +
geom_tile(aes(fill = value)) +
scale_fill_viridis_c()
7.4 quad_continuous()
quad_continuous()
align continuous variables and is functionally equivalent to the ggside package. For convenience, ggside()
is provided as an alias for quad_continuous()
. This layout is particularly useful for adding metadata or summary graphics along a continuous axis.
ggside(mpg, aes(displ, hwy, colour = class)) +
geom_point(size = 2) +
# initialize top annotation
anno_top(size = 0.3) +
# add a plot in the top annotation
ggalign() +
geom_density(aes(displ, y = after_stat(density), colour = class), position = "stack") +
# initialize right annotation
anno_right(size = 0.3) +
# add a plot in the right annotation
ggalign() +
geom_density(aes(x = after_stat(density), hwy, colour = class),
position = "stack"
&
) theme_bw()
ggside()
allows facetting for the main plot, which should also be applied to the annotations for proper alignment.
<- iris
i2 $Species2 <- rep(c("A", "B"), 75)
i2ggside(i2, aes(Sepal.Width, Sepal.Length, color = Species)) +
geom_point(size = 2) +
facet_grid(Species ~ Species2) +
anno_top(size = 0.3) +
ggalign() +
geom_density(aes(Sepal.Width, y = after_stat(density), colour = Species),
position = "stack"
+
) facet_grid(cols = vars(Species2)) +
anno_right(size = 0.3) +
ggalign() +
geom_density(aes(x = after_stat(density), Sepal.Length, colour = Species),
position = "stack"
+
) facet_grid(rows = vars(Species)) &
theme_bw()
If an annotation contains multiple plots, it can be tedious to add the same element to each one individually. One way to simplify this is by creating an external stack_layout()
and adding the desired elements using the &
operator. Then, you can add this stack_layout()
to the quad_layout()
. In Chapter 10, I will introduce another more powerful operator that seamlessly combines with the +
operator, allowing you to add elements to multiple plots at once.
7.5 quad_layout()
This function arranges plots around the quad-sides of a main plot, aligning both horizontal and vertical axes, and can handle either discrete or continuous variables.
- If
xlim
is provided, a continuous variable will be required and aligned in the vertical direction. Otherwise, a discrete variable will be required and aligned. - If
ylim
is provided, a continuous variable will be required and aligned in the horizontal direction. Otherwise, a discrete variable will be required and aligned.
quad_layout(small_mat, xlim = NULL) +
geom_boxplot(aes(value, .discrete_y, fill = .row_names)) +
scale_fill_brewer(palette = "Dark2") +
layout_title("quad_layout(xlim = ...)")
quad_layout(small_mat, ylim = NULL) +
geom_boxplot(aes(.discrete_x, value, fill = .column_names)) +
scale_fill_brewer(palette = "Dark2") +
layout_title("quad_layout(ylim = ...)")
As discussed in Section 3.4, quad_anno()
will always attempt to initialize a stack_layout()
with the same alignment as the current direction. For top and bottom annotations in quad_layout(xlim = ...)
, and left and right annotations in quad_layout(ylim = NULL)
, quad_anno()
will not initialize the annotation due to inconsistent data types.
<- quad_layout(small_mat, xlim = NULL) +
quadh anno_top()
#> Warning: `data` in `quad_layout()` is a double matrix, but the top annotation stack need
#> a <data.frame>, won't initialize the top annotation stack
<- quad_layout(small_mat, ylim = NULL) +
quadv anno_left()
#> Warning: `data` in `quad_layout()` is a double matrix, but the left annotation stack
#> need a <data.frame>, won't initialize the left annotation stack
Manual adding of a stack_layout()
is required in such cases, you can set initialize = FALSE
to prevent the warning message.
<- quad_layout(small_mat, xlim = NULL) +
quadh anno_top(initialize = FALSE)
<- quad_layout(small_mat, ylim = NULL) +
quadv anno_left(initialize = FALSE)
+
quadh stack_continuous("v", mpg) +
# add a plot in the top annotation
ggalign(mapping = aes(displ, hwy, colour = class)) +
geom_point(aes(displ, hwy, colour = class)) +
quad_active() +
geom_boxplot(aes(value, .discrete_y, fill = .row_names)) +
scale_fill_brewer(palette = "Dark2")+
layout_title("quad_alignh()")
+
quadv stack_continuous("h", mpg) +
# add a plot in the left annotation
ggalign(mapping = aes(displ, hwy, colour = class)) +
geom_point(aes(displ, hwy, colour = class)) +
quad_active() +
geom_boxplot(aes(.discrete_x, value, fill = .column_names)) +
scale_fill_brewer(palette = "Dark2") +
layout_title("quad_alignv()")
Alternatively, you can set initialize = TRUE
, which will initialize the annotation stack layout with no data. In this case, you must provide data
in each plot within the annotation.
quad_layout(small_mat, xlim = NULL) +
geom_boxplot(aes(value, .discrete_y, fill = .row_names)) +
scale_fill_brewer(palette = "Dark2") +
anno_top(initialize = TRUE) +
ggalign(data = mpg, aes(displ, hwy, colour = class)) +
geom_point(aes(displ, hwy, colour = class))+
layout_title("quad_alignh()")
quad_layout(small_mat, ylim = NULL) +
geom_boxplot(aes(.discrete_x, value, fill = .column_names)) +
scale_fill_brewer(palette = "Dark2") +
anno_left(initialize = TRUE) +
ggalign(data = mpg, aes(displ, hwy, colour = class)) +
geom_point(aes(displ, hwy, colour = class))+
layout_title("quad_alignv()")
In the next chapter, we will explore even more advanced techniques for combining multiple quad_layout()
s. These methods will provide you with the tools to manage more complex plot arrangements and make your visualizations even more flexible and powerful.