4  Fine-Grained Alignment Control

The ggalign package provides six free_ functions that give you precise control over plot alignment behavior by selectively disabling alignment constraints for specific plot elements in align_plots().

Code
library(ggalign)
#> Loading required package: ggplot2
#> 
#> Attaching package: 'ggalign'
#> The following object is masked from 'package:ggplot2':
#> 
#>     element_polygon

4.1 Position String Notation

Most free_ functions use a consistent "tlbr" notation system where each letter represents a side of the plot:

  • t: top
  • l: left
  • b: bottom
  • r: right

First, let’s create some example plots:

# A simple scatter plot
p_simple <- ggplot(mtcars) +
    geom_point(aes(mpg, disp))

# Create a plot with long axis labels that causes alignment issues
p_wide_labels <- ggplot(mtcars) +
    geom_bar(aes(y = factor(gear), fill = factor(gear))) +
    scale_y_discrete(
        name = NULL,
        labels = c(
            "3 gears are often enough",
            "But, you know, 4 is a nice number",
            "I would def go with 5 gears in a modern car"
        )
    )

4.2 free_align()

By default, align_plots() aligns plot panels so axes match. This can cause excessive spacing when plots differ in axis label lengths. free_align() disables panel alignment on specified sides.

# Problem: When combined, it looks bad due to forced alignment
align_plots(p_simple, p_wide_labels, ncol = 1L)

# Solution: Use free_align to prevent panel alignment
align_plots(p_simple, free_align(p_wide_labels), ncol = 1L)

# Partial solution: Free only the left side to maintain right alignment
align_plots(p_simple, free_align(p_wide_labels, axes = "l"), ncol = 1L)

4.3 free_space() - Space Constraint Removal

free_space() removes the allocated space for plot elements when aligning. This is particularly useful for removing padding introduced by long axis labels or titles.

align_plots(p_simple, free_space(p_wide_labels, spaces = "l"), ncol = 1L)

While it may not appear impactful on its own, free_space() is often essential when used together with free_border().

4.4 free_border()

free_border() attaches borders (e.g., axis titles, tick marks) directly to the plot panel. This keeps them visually close to the panel during alignment.

align_plots(free_border(p_simple, borders = "l"), p_wide_labels, ncol = 1L)

However, free_border() does not remove the space these components occupy. This means that, although the border (e.g., axis title) follows the plot panel more tightly in p_simple, the space reserved for it still exists. During alignment, this space is added to p_wide_labels, potentially adding unnecessary spaces.

To fully eliminate the size contribution of the border, we often combine free_border() with free_space():

align_plots(
    free_space(free_border(p_simple, borders = "l"), spaces = "l"),
    p_wide_labels,
    ncol = 1L
)

This removes the reserved size on the left side (spaces = “l”), ensuring clean, panel-based alignment without extra padding.

4.5 free_lab()

free_lab() is similar to free_border(), but only attaches axis titles and tick labels, not full borders. It’s mainly included for completeness; in most cases, combining free_border() and free_space() is sufficient.

4.6 free_vp()

The free_vp() function allows you to customize the grid viewport when aligning plots, giving you precise control over plot positioning and sizing. This is useful for precisely placing plots when alignment alone is insufficient.

p1 <- ggplot(mtcars) +
    geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) +
    geom_boxplot(aes(gear, disp, group = gear))
# Blank line at the beginning to keep height consistent


align_plots(p1, p2, ncol = 2L)

align_plots(p1, 
    free_vp(p2, height = unit(0.8, "npc"), just = "bottom", y = 0), 
    ncol = 2L
)

4.7 free_guide()

The free_guide() function allows you to override the guides argument for a single plot.

p_right <- ggplot(mtcars) +
    geom_point(aes(hp, wt, colour = mpg)) +
    patch_titles("right") +
    labs(color = "right")
p_top <- p_right +
    patch_titles("top") +
    scale_color_continuous(
        name = "top",
        guide = guide_colorbar(position = "top")
    )
p_left <- p_right +
    patch_titles("left") +
    scale_color_continuous(
        name = "left",
        guide = guide_colorbar(position = "left")
    )
p_bottom <- p_right +
    patch_titles("bottom") +
    scale_color_continuous(
        name = "bottom",
        guide = guide_colorbar(position = "bottom")
    )
align_plots(
    free_guide(p_right, NULL),
    free_guide(p_bottom, NULL),
    free_guide(p_top, NULL),
    free_guide(p_left, NULL),
    guides = "tlbr"
)

You can also specify which guide positions to be collected for individual plots.

align_plots(
    free_guide(p_right, "r"),
    free_guide(p_bottom, "b"),
    free_guide(p_top, "t"),
    free_guide(p_left, "l")
)