Draws a lattice-like matrix of panels in base graphics with identical plot region sizes, panel strips, axes on the outer panels only and a user-supplied panel function for the content. Panel gaps are defined in margin lines and remain exact, independent of device size and strip height, as the strip space is reserved separately in the layout.
Arguments
- samples
a list of samples, each a list (or data.frame) with components
xandy.- dim
integer vector of length 2, the number of rows and columns of the panel matrix,
c(nrow, ncol).- panelFun
the panel function, called per panel as
panelFun(x, y, col, pch, ...)with a fully set up coordinate system. Components of a sample beyondxandyare passed on under their own names, so a panel can carry per-panel data of its own - confidence bounds, weights, labels. They are only passed to apanelFunthat can accept them (a matching formal, or...), so panel functions written for the two-component form keep working unchanged.- cols
the colors for the panels, recycled to the number of samples. Default is
hcl.colors(n, "Dark 3").- stripLabels
the labels for the panel strips. Default is
names(samples)where the samples are named, otherwise the sequence alongsamples.- main
the main title, placed in the outer margin.
- xlab, ylab
the axis labels, placed in the outer margins.
- xlim, ylim
the axis limits. A numeric vector of length 2 (or
NULL, the default, for the range over all samples) binds every panel to the same scale."free"gives each panel its own scale, taken from its own sample. A list of length 2 vectors, one per sample, does the same with limits you choose; a list of length 1 is recycled. See the section on free scales.- mar
the margins around the whole panel matrix in lines,
c(bottom, left, top, right). The bottom and left margins hold the axis annotation of the outer panels.- oma
the outer margins in lines, holding
xlab,ylabandmain.- horiz
the horizontal gap between adjacent columns in margin lines.
- vert
the vertical gap between adjacent rows in margin lines. Default is
horiz, yielding physically equal gaps.- strip
controls the panel strips, evaluated by bedrock::callIf:
TRUE(default) draws strips with default settings,FALSE/NULL/NAsuppresses them (no space is reserved), a named list is passed as arguments totitleRect(), e.g.list(bg = "steelblue", col = "white", line = 1.5). Thelabelargument is set per panel fromstripLabelsand cannot be overridden.- bg
the background color of the plot regions.
- grid
controls the grid lines, evaluated by bedrock::callIf:
TRUE(default) draws grid lines at the positions ofaxTicks()with default settings (col = "grey85", lwd = 0.8),FALSE/NULL/NAsuppresses them, a named list is passed as arguments toabline(), e.g.list(col = "white", lty = "dotted"). The default positionsvandhcan be overridden, e.g.list(v = seq(0, 20, 5)).- cex
the character expansion used inside the panels (axis annotation, strip labels, panel content) and as unit for the panel margin lines. Default is 0.66, matching R's own reduction in multi-figure layouts. Set deterministically after each
plot.new(), see Details.- pch
the plotting character, passed to
panelFun.- ...
the dots are passed to
panelFun.
Value
Invisibly returns a list with the realized geometry:
horiz, vert, strip_line (reserved strip height
in lines) and the common plot region size plot_width_in,
plot_height_in in inches.
Details
The available device area inside the outer margins is partitioned with
layout() such that all plot regions have exactly the same
size in inches. The horizontal gap between two adjacent columns is
horiz margin lines, the vertical gap between two adjacent rows is
vert lines. Since margin lines have the same physical size in
both directions, horiz == vert yields visually equal gaps.
Bound and free scales
By default all panels share one coordinate system, and the axes are drawn on the outer panels only - the arrangement that makes small multiples comparable at a glance.
Passing xlim = "free" - or a list of limits, for control over
the individual panels - frees that dimension:
every panel gets its own limits, and with them its own axis, because an
outer axis would no longer describe the panels above or beside it.
The layout answers for this - a freed dimension reserves the full
mar on every panel edge that now carries annotation, not just on
the outer ones, so the panels stay equal in size and the tick labels
have room.
Free scales cost what they free: panels can no longer be compared by position, only by shape. The natural case is a set of diagnostics of one model against different predictors - the residual scale is shared and worth comparing, the predictor scales are not commensurable at all.
The strip is drawn with titleRect() above each panel. Its
height (line argument of titleRect) is reserved in the top
margin of every panel, so the strip never eats into the gap between the
rows.
Note that plot.new() silently reduces cex (and with
it csi, the physical size of a margin line) in layouts with more
than two regions, which would make the realized panel margins deviate
from the computed layout. The function therefore controls the character
size deterministically via its cex argument and sets the panel
margins in inches (mai/omi), so that all plot regions are
exactly equal in size.
See also
graphics::layout, titleRect, bedrock::callIf
Other graphics.layout:
abcCoords(),
axTicks,
axisBreak(),
isValidPlotRegion(),
lineToUser(),
mar(),
spreadOut()
Examples
samples <- lapply(split(ChickWeight, ChickWeight$Chick)[1:25],
function(z) list(x = z$Time, y = z$weight))
my_panel <- function(x, y, col, pch = 16, ...) {
points(x, y, pch = pch, col = col)
abline(lm(y ~ x), lwd = 1)
}
plotFacet(samples, dim = c(5, 5), panelFun = my_panel,
xlab = "Time", ylab = "Weight", main = "ChickWeight",
strip = list(bg = "grey80", cex = 0.8))
# free x scales: mpg against four predictors, each on its own range,
# with a shared y scale. The regression band travels in the samples and
# reaches the panel function under its own names.
vars <- c("disp", "hp", "wt", "qsec")
samples <- lapply(vars, function(v) {
ord <- order(mtcars[[v]])
ci <- predict(lm(reformulate(v, "mpg"), mtcars), interval = "confidence")
list(x = mtcars[[v]][ord], y = mtcars$mpg[ord],
lci = ci[ord, "lwr"], uci = ci[ord, "upr"])
})
panelBand <- function(x, y, lci, uci, col, pch = 16, ...) {
polygon(c(x, rev(x)), c(uci, rev(lci)), col = "grey85", border = NA)
points(x, y, col = col, pch = pch)
}
plotFacet(setNames(samples, vars), dim = c(2, 2), panelFun = panelBand,
xlim = "free", ylab = "mpg",
main = "mpg against four predictors")
