ggplot2::facet_wrap
facet_wrap arranges a sequence of panels into a 2D grid. It takes a 1D set of facets — produced by one or more categorical variables — and wraps them into rows and columns. This is the right choice when you have a single faceting variable with many levels, or multiple variables but not in a full grid.
Signature
facet_wrap(
facets,
nrow = NULL,
ncol = NULL,
scales = "fixed",
space = "fixed",
shrink = TRUE,
labeller = "label_value",
as.table = TRUE,
switch = deprecated(),
drop = TRUE,
dir = "h",
strip.position = "top",
axes = "margins",
axis.labels = "all"
)
Returns: A FacetWrap object (a ggproto object controlling panel layout).
Parameters
Facet Specification
| Parameter | Description |
|---|---|
facets | Use vars(var1, var2) to specify one or more faceting variables. Also accepts a formula (~var) or a character vector (c("var1", "var2")) for compatibility. |
nrow | Number of rows in the grid. |
ncol | Number of columns in the grid. |
You specify either nrow or ncol, or both. If you specify neither, ggplot2 picks a layout that keeps panels roughly square and fills the space efficiently.
Scale Behavior
| Parameter | Description |
|---|---|
scales | "fixed" (default) — all panels share the same scale. "free" — each panel gets its own scale based on its data. "free_x" — x scale free, y scale shared. "free_y" — y scale free, x scale shared. |
space | "fixed" (default) — all panels have the same size. "free_x" — panel widths proportional to x range, constrained to one row. "free_y" — panel heights proportional to y range, constrained to one column. |
Panel Appearance
| Parameter | Description |
|---|---|
shrink | TRUE (default) — scales shrink to fit the statistics output. FALSE — scales use the raw data range before statistical transformation. |
drop | TRUE (default) — unused factor levels are dropped automatically. FALSE — all factor levels are shown regardless of whether they appear in the data. |
strip.position | Where to place facet labels: "top" (default), "bottom", "left", "right". |
dir | Layout direction: "h" (horizontal, default) fills row-by-row; "v" fills column-by-column. You can also use two-letter combos like "tr" (top-right start, fill downward). |
Axis Display
| Parameter | Description |
|---|---|
axes | "margins" (default) — axes drawn at exterior margins only. "all" — draw axes at all panels. "all_x" — x axes at all panels. "all_y" — y axes at all panels. |
axis.labels | "all" (default) — labels shown on all interior axes. "margins" — labels only on exterior axes. "all_x" / "all_y" — labels only on interior axes in that direction. |
Basic Example
library(ggplot2)
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(class))
This produces one panel per class value, arranged in a grid. The number of rows and columns is chosen automatically to keep panels roughly square.
Controlling the Grid
# 4 rows, auto number of columns
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(class), nrow = 4)
# 2 columns, auto number of rows
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(class), ncol = 2)
Specifying both nrow and ncol gives you precise control over the layout.
Free Scales
# Each panel scales independently
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(class), scales = "free")
Free scales make it easier to spot within-panel patterns, but harder to compare values across panels. Use "free_x" when x ranges differ but y ranges should be comparable, or "free_y" for the opposite.
Multiple Faceting Variables
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(cyl, drv))
When you supply multiple variables to vars(), facet_wrap creates one panel per combination — like a grid without the row/column structure of facet_grid. The grid layout follows the same wrapping rules.
Labeller Control
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(cyl, drv), labeller = label_both)
label_both shows both variable names and values (e.g., “cyl: 4, drv: f”). Other options include label_value (values only, default), label_parsed (treats labels as plotmath expressions), and custom functions.
Reordering Panels
The order of panels follows the order of factor levels. To change the order:
mpg$class_ordered <- reorder(mpg$class, mpg$displ)
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(class_ordered))
reorder() sorts factor levels by a second variable — here, median displacement per class.
Strip Position
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(class), strip.position = "bottom")
Moving strips to the bottom works well as a subtitle for the x-axis, especially with free x scales. "left" is useful when you have narrow labels or many panels.
Repeated Data Across Panels
ggplot(mpg, aes(displ, hwy)) +
geom_point(data = transform(mpg, class = NULL), colour = "grey85") +
geom_point() +
facet_wrap(vars(class))
By setting class = NULL in a separate layer’s data, you can display the full dataset as a background in every panel while the foreground data is filtered per panel.
Axes and Labels
# Show axes at every panel
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(class), axes = "all")
# Show y-axis labels at interior panels too
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(vars(class), axis.labels = "all_y")
When scales are fixed, you can choose which panels get axes and which get axis labels. "all" for axes draws the axis lines everywhere; "all_x" / "all_y" targets specific directions.
facet_wrap vs facet_grid
| Feature | facet_wrap | facet_grid |
|---|---|---|
| Variables | Any number, wrapped | Exactly row + col variables |
| Grid shape | Automatic 2D layout | Explicit row × column |
| Best for | Single variable with many levels | Two variables in a true grid |
| Scales | Per-panel or shared | Per-panel or shared |
| Empty cells | Possible (irregular grid) | Never (full rectangular grid) |
Use facet_wrap when you have one variable (or two without needing a true grid). Use facet_grid when you want a fixed row × column layout.
See Also
- /tutorials/r-data-visualization/faceting-in-ggplot2/ — faceting tutorial with both facet_wrap and facet_grid
- /tutorials/r-data-visualization/ggplot2-basics/ — getting started with ggplot2
- /tutorials/r-data-visualization/ggplot2-facets-and-themes/ — themes and styling facets