ggpatchy adds a pattern aesthetic to ggplot2 geoms.
Patterns are rendered via native grid graphics — no ImageMagick or
external raster dependencies are required.
Bar and column charts
geom_col_pattern() and geom_bar_pattern()
are drop-in replacements for geom_col() and
geom_bar(). Map pattern to a discrete variable
with scale_pattern_manual() or
scale_pattern_discrete().
df <- data.frame(
category = c("A", "B", "C", "D"),
value = c(3.2, 5.1, 4.0, 2.7)
)
ggplot(df, aes(category, value, fill = category, pattern = category)) +
geom_col_pattern() +
scale_pattern_manual(values = c(
A = "hatch", B = "crosshatch", C = "dots", D = "vertical"
)) +
scale_fill_brewer(palette = "Pastel1") +
theme_minimal() +
labs(title = "geom_col_pattern()")
geom_bar_pattern() uses stat = "count":
ggplot(mpg, aes(class, fill = class, pattern = class)) +
geom_bar_pattern() +
scale_pattern_discrete() +
scale_fill_brewer(palette = "Set3") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 30, hjust = 1)) +
labs(title = "geom_bar_pattern() with scale_pattern_discrete()")
Polygons
geom_polygon_pattern() clips patterns to the exact
polygon boundary, not just the bounding box. This means concave shapes
like crescents or L-shapes are handled correctly.
theta <- seq(0, 2 * pi, length.out = 7)[-7]
hex <- data.frame(x = cos(theta), y = sin(theta))
ggplot(hex, aes(x, y)) +
geom_polygon_pattern(
pattern = "hatch",
fill = "lightyellow",
pattern_colour = "goldenrod",
pattern_angle = 30,
pattern_spacing = 4
) +
coord_fixed() +
theme_void() +
labs(title = "geom_polygon_pattern() on a hexagon")
Ribbon charts
geom_ribbon_pattern() adds patterns to confidence bands
or any region defined by ymin and ymax.
x <- seq(0, 2 * pi, length.out = 80)
df <- data.frame(x = x, ymin = sin(x) - 0.3, ymax = sin(x) + 0.3)
ggplot(df, aes(x, ymin = ymin, ymax = ymax)) +
geom_ribbon_pattern(
pattern = "hatch",
fill = "lightblue",
pattern_colour = "steelblue"
) +
theme_minimal() +
labs(title = "geom_ribbon_pattern() — confidence band")
Multiple groups with different patterns:
df2 <- data.frame(
x = c(x, x),
ymin = c(sin(x) - 0.2, cos(x) + 0.5),
ymax = c(sin(x) + 0.2, cos(x) + 1.0),
group = rep(c("sin", "cos"), each = length(x)),
pattern = rep(c("hatch", "crosshatch"), each = length(x)),
fill = rep(c("lightblue", "lightyellow"), each = length(x))
)
ggplot(df2, aes(x, ymin = ymin, ymax = ymax,
group = group, fill = fill, pattern = pattern)) +
geom_ribbon_pattern(alpha = 0.8) +
scale_pattern_identity(guide = "legend") +
scale_fill_identity() +
theme_minimal() +
labs(title = "geom_ribbon_pattern() — two groups")
Area charts
geom_area_pattern() mirrors geom_area(): it
sets ymin = 0 automatically and defaults to
position = "stack".
df3 <- data.frame(
x = rep(1:8, 2),
y = c(1, 3, 2, 4, 3, 2, 4, 3,
2, 1, 3, 2, 1, 3, 2, 1),
group = rep(c("Group A", "Group B"), each = 8),
pattern = rep(c("hatch", "crosshatch"), each = 8)
)
ggplot(df3, aes(x, y, fill = group, pattern = pattern)) +
geom_area_pattern(position = "stack", alpha = 0.85) +
scale_pattern_identity(guide = "legend") +
scale_fill_brewer(palette = "Pastel1") +
theme_minimal() +
labs(title = "geom_area_pattern() — stacked")
Violin charts
geom_violin_pattern() adds patterns to violin plots. Use
it as a drop-in replacement for geom_violin().
ggplot(mpg, aes(class, hwy, fill = class, pattern = class)) +
geom_violin_pattern(pattern_colour = "grey30") +
scale_pattern_discrete() +
scale_fill_brewer(palette = "Pastel1") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 30, hjust = 1)) +
labs(title = "geom_violin_pattern()")
Density plots
geom_density_pattern() extends
geom_density() for pattern fills on smooth density
estimates.
ggplot(mpg, aes(hwy, fill = drv, pattern = drv)) +
geom_density_pattern(alpha = 0.7, pattern_colour = "grey20") +
scale_pattern_manual(values = c("4" = "hatch", "f" = "crosshatch", "r" = "dots")) +
scale_fill_brewer(palette = "Pastel2") +
theme_minimal() +
labs(title = "geom_density_pattern()")
Rectangles and tiles
geom_rect_pattern() and geom_tile_pattern()
add pattern overlays to rectangle geoms.
geom_tile_pattern() is convenient for heatmap-style layouts
where cells are specified by centre coordinates.
blocks <- data.frame(
xmin = c(0, 1, 2, 0, 1, 2),
xmax = c(1, 2, 3, 1, 2, 3),
ymin = c(0, 0, 0, 1, 1, 1),
ymax = c(1, 1, 1, 2, 2, 2),
pattern = c("hatch", "crosshatch", "dots", "vertical", "horizontal", "weave")
)
ggplot(blocks, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax,
fill = pattern, pattern = pattern)) +
geom_rect_pattern(pattern_colour = "grey30") +
scale_pattern_identity() +
scale_fill_brewer(palette = "Pastel1") +
coord_fixed() +
theme_void() +
labs(title = "geom_rect_pattern() — all six line/dot patterns")
Choropleth maps
geom_sf_pattern() works with sf geometry columns. It
uses pattern to add a second encoding channel alongside fill colour,
which is useful for accessibility (grayscale printing, colour-vision
deficiency). See the Mapping with Patterns vignette for
full examples with the NC counties and US states datasets.
Pattern reference
Built-in patterns:
| Name | Description | Respects pattern_angle? |
|---|---|---|
none |
No pattern (fill only) | — |
hatch |
Diagonal lines | Yes |
crosshatch |
Crossed diagonal lines | Yes |
horizontal |
Horizontal lines | No (fixed) |
vertical |
Vertical lines | No (fixed) |
dots |
Regular dot grid | No (fixed) |
weave |
Woven over/under line texture | No (fixed) |
pattern_spacing is in millimetres:
pattern_spacing = 5 places pattern elements 5 mm apart on
every shape at every size. Visual density is uniform across all shapes
in the same plot. Custom patterns can be registered with
register_pattern().
Known limitations
stat = "identity" with
geom_violin_pattern() requires a violinwidth
column. The default stat ("ydensity") computes
violinwidth automatically from your raw data. If you pass
stat = "identity" with pre-summarised density data, your
data frame must include a violinwidth column (values in [0,
1] giving the normalised half-width at each y level). If
the column is absent, geom_violin_pattern() emits an
informative message and skips that group rather than crashing.
orientation = "y" (horizontal) is not supported
for pattern overlays. geom_violin_pattern(),
geom_ribbon_pattern(), and geom_area_pattern()
all skip the pattern when orientation = "y" or
flipped_aes = TRUE. The base shape still renders correctly.
Use coord_flip() on a vertical geom as a workaround.
Non-Cartesian coordinates: Patterns are drawn in
screen (npc) space after coord$transform(). Under
coord_polar or coord_sf the pattern lines
remain straight in screen pixels rather than following the coordinate
curvature.