Draws the samples in two dimensions of an embedding, such as UMAP
coordinates from embed::step_umap(), principal component scores from
recipes::step_pca(), robpca() or stats::prcomp(), colored by a
variable.
Usage
plot_embedding(
data,
x = NULL,
y = NULL,
colour = NULL,
size = 2,
alpha = 0.8,
ellipse = FALSE,
conf_level = 0.975,
robust = FALSE,
distribution = "normal",
hotelling = "none",
k = 2,
t2_method = "f",
flag = FALSE,
label = NULL,
biplot = FALSE,
biplot_top = 10,
aspect_ratio = 0.7,
title = NULL,
legend_title = NULL,
palette = NULL,
shapes = TRUE,
legend = c("right", "bottom", "top", "inside", "none"),
panel = c("shaded", "white"),
caption = TRUE,
base_size = 11
)Arguments
- data
The embedding: a data frame (such as a baked recipe), a matrix, a
stats::prcomp()fit, or an object ofrobpca(),rospca()ormacropca().- x, y
The columns of the axes, unquoted or as strings. By default, the first two embedding coordinates (see details).
- colour
The variable coloring the points: a column of
data(unquoted or as a string), or a vector with one value per sample.- size
The size of the points: a number (default 2), or a numeric column of
dataor vector with one value per sample to vary it.- alpha
The opacity of the points.
- ellipse
A logical: draw confidence ellipses (
FALSE, default). Needs the ConfidenceEllipse package.- conf_level
The confidence level(s) of the ellipses, confidence and \(T^2\): one or more values between 0 and 1. Default is 0.975. The samples beyond a \(T^2\) limit are flagged at the highest level.
- robust
A logical: robust ellipses (
FALSE, default).- distribution
The quantile of the ellipses:
"normal"(default, chi-square) or"hotelling".- hotelling
Hotelling's \(T^2\) ellipses and outliers:
"none"(default),"all"(all samples) or"group"(within the groups of a discretecolour). Needs the HotellingEllipse package (1.3.0 or later).- k
The number of components of \(T^2\): the two axes, then the next embedding coordinates. Default is 2.
- t2_method
The distribution of the \(T^2\) limits:
"f"(default),"beta"or"new"(seehotelling_t2()). Ignored for a robust PCA, whose limit is the chi-square quantile of ROBPCA.- flag
A logical: circle in red the samples beyond the \(T^2\) limit (
FALSE, default).- label
The labels of the samples beyond the \(T^2\) limit, whether or not they are circled:
NULLorFALSE(default) for none,TRUEfor their row numbers, or a column ofdataor a vector with one value per sample.- biplot
A logical: draw the loadings over the scores (
FALSE, default).- biplot_top
The number of loadings drawn as labeled arrows. Default is 10.
- aspect_ratio
The ratio of the height to the width of the panel. Default is 0.7;
NULLlets the panel fill the plot;"equal"gives the two axes the same scale, so that the distances between the samples are not distorted (for scores in the same units).- title
The plot title.
- legend_title
The title of the legend of
colour. Default is its name; give it with units, such as"K (%)".- palette
The colors of
colour:NULL(default: Dark2 for up to 8 groups, viridis for a numeric variable), the name of a viridis palette ("viridis","magma","cividis", ...) or a vector of colors.- shapes
A logical: give each group of a discrete
colourits own point shape (up to 6 groups), so that the groups stay apart in grayscale (TRUE, default).- legend
The position of the legend:
"right"(default),"bottom","top","inside"(the top right corner of the panel) or"none".- panel
"shaded"(default), the panel grey outside the outermost ellipse and white inside, or"white".- caption
TRUE(default), a caption saying what the ellipses and limits are;FALSE, no caption; or a caption of your own.- base_size
The size of the text, in points. Default is 11; use the text size of the journal (often 7 to 9 points) for a figure saved at its printed size. The points, lines and labels scale with it.
Details
By default, the axes are the first two columns named like embedding
coordinates (UMAP1, PC1, Comp1, ...; the name followed by a
number), or else the first two numeric columns. A numeric colour uses
a continuous viridis scale, other types a discrete palette.
With ellipse = TRUE, a confidence ellipse is drawn for each group of a
discrete colour (or for all the samples otherwise), with
ConfidenceEllipse::confidence_ellipse(), at each level of conf_level
(0.975 by default). It covers the region expected to hold that share of
the samples of the group if they follow a
bivariate normal distribution, from their mean and covariance, or from
robust estimates (MCD) with robust = TRUE, which resist outlying
samples. distribution = "hotelling" uses the quantile of Hotelling's
\(T^2\) distribution, which accounts for the uncertainty of the
estimates and suits small groups. Robust estimates need larger groups
(the MCD fits a subset of about three quarters of the samples): with
fewer than about 10 samples per group, their ellipses can be flat or
leave out several samples. Groups with fewer than 4 samples get no
ellipse.
With hotelling = "all", the ellipses of Hotelling's \(T^2\) at each
level of conf_level (97.5% by default) are drawn for all the samples,
and the samples beyond the limit at the highest level of \(T^2\) on k
components are counted in the subtitle, circled in red with
flag = TRUE and labeled with label (each independently of the other):
the classical outlier limits of a score plot. For a PCA model (stats::prcomp(), robpca(), rospca() or
macropca()), \(T^2\) is that of the model: the scores divided by the
variances of the components (the robust eigenvalues of a robust fit), so
the ellipses are centered at 0 with the axes of the components, and
semi-axes \(\sqrt{\lambda_a L}\) for the limit \(L\). The limit is
the F (or Beta) limit of hotelling_t2() for a stats::prcomp() fit, and
the chi-square quantile of ROBPCA for a robust fit, whose flagged samples
are then the leverage points of plot_outlier_map() (with k its
number of components and conf_level = 0.975). The scores of the
outlying samples then do not inflate or tilt the ellipses. For other
embeddings, \(T^2\) is computed from the mean and covariance of the
samples (with hotelling_t2() and HotellingEllipse::ellipseCoord()).
With hotelling = "group", each group of a discrete colour gets its own
ellipses and limits, from its mean and covariance, which flags the samples
atypical of their own group. The ellipses are labeled with their level
(instead of a legend), and drawn for the two components shown, while the
limits use k components, so with k > 2 a flagged sample can lie inside
the ellipses. With ellipse = TRUE, the confidence ellipses are always
computed from the samples shown. Without groups, ellipse = TRUE and
hotelling = "all" would draw two ellipses of all the samples: only the
\(T^2\) ellipse is drawn, with a warning. With groups, both are drawn:
the confidence ellipses of the groups and the \(T^2\) limits of all
the samples. \(T^2\) suits linear scores such as
PCA or PLS; on a UMAP
map, whose distances are not meaningful, prefer ellipse.
Style. The panel is grey outside the outermost ellipse (of
\(T^2\), or of each group) and white inside, so that the samples beyond
the limits stand out (panel = "white" for a white panel), with no grid
and a fixed aspect_ratio (0.7 by default; NULL lets the plot fill the
space, "equal" gives both axes the same scale), and thin light grey
lines through the origin (when it lies in the range of the samples, as for
centered scores). Without ellipses, the panel is white. The groups of a
discrete colour also get their own point shapes (shapes), and the axes
plain numbers. A caption says what the ellipses and limits are (their
level, distribution and estimates), which readers cannot tell from the
plot.
Publication figures. Make the plot at its printed size, with
base_size set to the text size of the journal, for example
ggsave("scores.pdf", p, width = 85, height = 75, units = "mm") with
base_size = 8 for a single column.
Axes. For a stats::prcomp() fit or a robust PCA, the axis titles
give the share of the variance of each component: of the total variance
for stats::prcomp(), and of the variance of the k components of the
model for robpca(), rospca() and macropca(), which estimate only
these. With groups, the ellipses (confidence, or \(T^2\) with
hotelling = "group") are filled with the color of their group.
Point size. size is a number, or a numeric variable (a column of
data or a vector with one value per sample), such as the concentration
of an element, which sets the size of each point, with a legend.
Biplot. With biplot = TRUE (for a stats::prcomp() fit or a robust
PCA), the loadings of the two components are drawn over the scores: all
the variables as faint points, and the biplot_top longest as labeled
arrows. For spectra, the arrows are the local peaks of the loading
length along the wavelength, one per emission line, labeled with their
wavelength. Each axis of loadings is scaled to the range of its scores,
and read on the top and right axes. A sample lies toward the arrows of
the variables in which it is high.
In a UMAP embedding, only the neighborhoods are meaningful: the sizes of
the clusters and the distances between them are not, and they change
with neighbors and min_dist. Read the plot as a map of which samples
are similar, not as a quantitative projection. When both axes are UMAP
coordinates (named UMAP1, UMAP2, ..., as by embed::step_umap()),
the lines through the origin are left out, and hotelling ("all" or
"group") is ignored, with a warning: its \(T^2\) limits assume linear
scores.
Examples
# robust PCA of the forage spectra, with the Hotelling's T-squared limit
if (rlang::is_installed("HotellingEllipse", version = "1.3.0")) {
data(forageLIBS)
# the 380-430 nm window (Ca II H and K lines)
wl <- suppressWarnings(as.numeric(names(forageLIBS)))
set.seed(1)
forageLIBS[which(wl > 380 & wl < 430)] |>
center() |>
robpca(k = 2) |>
plot_embedding(hotelling = "all", flag = FALSE, label = TRUE)
}
# PCA of the K I lines, the samples grouped by potassium level, for a
# journal column
if (rlang::is_installed("ConfidenceEllipse")) {
data(forageLIBS)
wl <- suppressWarnings(as.numeric(names(forageLIBS)))
pca <- stats::prcomp(forageLIBS[which(wl > 760 & wl < 772)])
level <- cut(forageLIBS$K, 3, labels = c("Low K", "Mid K", "High K"))
p <- plot_embedding(pca, colour = level, ellipse = TRUE, legend_title = "Potassium",
legend = "bottom", base_size = 8)
p
# ggplot2::ggsave("scores.pdf", p, width = 85, height = 80, units = "mm")
}
#> Warning: RGL: unable to open X11 display
#> Warning: 'rgl.init' failed, will use the null device.
#> See '?rgl.useNULL' for ways to avoid this warning.
# \donttest{
# UMAP map of the iris flowers, from embed::step_umap(): no lines through
# the origin, whose position means nothing on such a map
if (rlang::is_installed(c("recipes", "embed"))) {
set.seed(1)
umap <- recipes::recipe(Species ~ ., data = iris) |>
recipes::step_normalize(recipes::all_predictors()) |>
embed::step_umap(recipes::all_predictors(), neighbors = 15) |>
recipes::prep() |>
recipes::bake(new_data = NULL)
plot_embedding(umap, colour = Species, title = "UMAP of the iris flowers")
}
# }
