The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Patchwork Integration

Gilles Colling

2026-01-07

Overview

When combining multiple plots with patchwork, legends often need special handling:

ggguides provides collect_legends() and collect_axes() to address these challenges.

The Problem: Duplicate Legends

library(patchwork)

p1 <- ggplot(mtcars, aes(mpg, wt, color = factor(cyl))) +
  geom_point() + labs(title = "Plot 1", color = "Cylinders")
p2 <- ggplot(mtcars, aes(mpg, hp, color = factor(cyl))) +
  geom_point() + labs(title = "Plot 2", color = "Cylinders")

# Default patchwork: duplicate legends
p1 | p2

Basic Legend Collection

Use collect_legends() to gather legends from all plots in a composition:

collect_legends(p1 | p2)

Position Options

Control where the collected legend appears:

collect_legends(p1 | p2, position = "bottom")

collect_legends(p1 | p2, position = "left")

Stacked Plots

For vertically stacked plots, legends can be centered or span the full height. Using different plot heights makes the spanning behavior more visible.

Default: Centered

# Create plots with different heights using plot_layout
p3 <- ggplot(mtcars, aes(mpg, disp, color = factor(cyl))) +
  geom_point() + labs(title = "Plot 3", color = "Cylinders")

# Stack with different heights: 1, 1/2, 1/4
stacked <- (p1 / p2 / p3) + plot_layout(heights = c(4, 2, 1))
collect_legends(stacked, position = "right")

Spanning Full Height

Use span = TRUE to make the legend fill the full height:

gt <- collect_legends(stacked, position = "right", span = TRUE)
grid::grid.draw(gt)

Attaching to Specific Rows

Attach the legend to specific row(s) instead of spanning all:

# Legend attached to row 1 only (the tallest plot)
gt <- collect_legends(stacked, position = "right", span = 1)
grid::grid.draw(gt)

# Legend attached to rows 1 and 2
gt <- collect_legends(stacked, position = "right", span = 1:2)
grid::grid.draw(gt)

Collecting Duplicate Axes

When stacking plots vertically, the x-axis may be duplicated. Use collect_axes() to remove redundant axes:

# Plots stacked vertically - x-axis is duplicated
p_top <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point() + labs(y = "Weight")

p_bottom <- ggplot(mtcars, aes(mpg, disp)) +
  geom_point() + labs(y = "Displacement")

# Without axis collection (both have x-axis)
p_top / p_bottom

# With axis collection (removes redundant x-axis from top)
collect_axes(p_top / p_bottom)

Combining with Styling

ggguides functions work together:

p1_styled <- p1 + legend_style(size = 11, title_face = "bold")
p2_styled <- p2 + legend_style(size = 11, title_face = "bold")

collect_legends(p1_styled | p2_styled, position = "right")

Complex Layouts

Handle more complex patchwork layouts:

p4 <- ggplot(mtcars, aes(qsec, wt, color = factor(cyl))) +
  geom_point() + labs(title = "Plot 4", color = "Cylinders")

# 2x2 grid
layout <- (p1 | p2) / (p3 | p4)
collect_legends(layout, position = "right")

cowplot / Grid Users

ggguides provides cowplot-compatible functions that work without patchwork:

get_legend() - Extract Legend

# Extract legend from a plot
leg <- get_legend(cp1)

# Use with cowplot::plot_grid() or grid::grid.draw()
grid::grid.newpage()
grid::grid.draw(leg)

shared_legend() - Combine Plots with Shared Legend

# Side-by-side with shared legend on right
gt <- shared_legend(cp1, cp2, ncol = 2, position = "right")
grid::grid.newpage()
grid::grid.draw(gt)

# Stacked with legend at bottom
gt <- shared_legend(cp1, cp2, cp3, ncol = 1, position = "bottom")
grid::grid.newpage()
grid::grid.draw(gt)

# 2x2 grid
gt <- shared_legend(cp1, cp2, cp3, cp4, ncol = 2, nrow = 2, position = "right")
grid::grid.newpage()
grid::grid.draw(gt)

All ggguides styling functions (legend_style(), legend_wrap(), etc.) work on individual plots regardless of layout package.

Summary

Function Purpose Key Parameters
collect_legends() Gather legends from patchwork position, span
collect_axes() Remove duplicate axes guides
get_legend() Extract legend as grob -
shared_legend() Combine plots with shared legend ncol, nrow, position

Learn more:

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.