Skip to content

Panels are misnamed within tableGrob for facet_wrap #6082

Closed
@nicholasdavies

Description

@nicholasdavies

I found a problem with the naming of panels (naming within the table grob) with facet_wrap; the panels are named in the wrong order. This is not really an issue in the normal course of ggplot2 use, but is confusing for people delving into the tableGrob / gtable structure of a ggplot2 plot.

For example, if you create a plot using facet_wrap() to lay out 2 rows and 3 columns of facets, the panel "cells" of the gtable are named (sensibly) panel-1-1, panel-2-1, panel-3-1, panel-1-2, panel-2-2, and panel-3-2. But the order of these names is wrong, so that the plot as laid out looks like this:

panel-1-1  panel-3-1  panel-2-2
panel-2-1  panel-1-2  panel-3-2

I expected the ordering of names to correspond to this layout:

panel-1-1  panel-2-1  panel-3-1
panel-1-2  panel-2-2  panel-3-2

Here is the code to reproduce the bug:

library(ggplot2)

df <- data.frame(x = 1:6)

plot <- ggplot(df) +
    geom_point(aes(x, x)) +
    facet_wrap(~x, nrow = 2)

gtable <- ggplotGrob(plot)
gtable$layout[grepl("^panel", gtable$layout$name), ]
#>    t  l  b  r z clip      name
#> 1 10  7 10  7 1  off panel-1-1
#> 2 15  7 15  7 1  off panel-2-1
#> 3 10 11 10 11 1  off panel-3-1
#> 4 15 11 15 11 1  off panel-1-2
#> 5 10 15 10 15 1  off panel-2-2
#> 6 15 15 15 15 1  off panel-3-2

Created on 2024-09-05 with reprex v2.1.0

If you look carefully at the output above, you will see how the naming of the panels doesn't correspond to the layout as indicated by t/l/b/r.

In the development version of ggplot2, the issue is in R/facet-.R, lines 238-243:

    # Set panel names
    table$layout$name <- paste(
      "panel",
      rep(seq_len(dim[2]), dim[1]),
      rep(seq_len(dim[1]), each = dim[2]),
      sep = "-"
    )

I believe these lines should instead be

    # Set panel names
    table$layout$name <- paste(
      "panel",
      rep(seq_len(dim[2]), each = dim[1]),
      rep(seq_len(dim[1]), dim[2]),
      sep = "-"
    )

or

    # Set panel names
    table$layout$name <- paste(
      "panel",
      rep(seq_len(dim[1]), dim[2]),
      rep(seq_len(dim[2]), each = dim[1]),
      sep = "-"
    )

(with the two rep lines switched) depending on whether you want the syntax to be panel-col-row or panel-row-col.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions