2

facet_grid and facet_wrap each have their own limitations.

facet_wrap does not have a space = "free" argument, leading to plots with unattractive y-axes (see Add space argument to facet_wrap for code)

enter image description here

facet_grid is limited by having labels on the side (see Add space argument to facet_wrap for code). enter image description here

Solutions have been offered to move facet_grid labels to the top (see ggplot2: Using gtable to move strip labels to top of panel for facet_grid).

Is it possible to use the ggplot2: Using gtable to move strip labels to top of panel for facet_grid solution to make a 2 column figure, such as would be created using the ncol = 2 argument with facet_wrap, or can the solution be accomplished using facet_wrap itself? The solution should look like below with y-axis spacing similar to the facet_grid example above.

enter image description here

Requirements are; labels on top, proper spacing on y-axis, and both x-axes use the same scale.

nateroe
  • 487
  • 3
  • 20
  • 2
    What does 'proper spacing on the y-axis' mean in this case? For example, in the 2nd row, you have a panel with 3 labels on the left, and on the right it has 10 labels. How should this be reconciled? – teunbrand Dec 15 '21 at 21:43
  • I want the spacing to be constant on the y-axis. Each row receives the same amount of space, as can be see in the ```facet_grid()``` example. The correct answer could have blank space at the bottom of a column. – nateroe Dec 16 '21 at 03:10

1 Answers1

2

Is this the output you're looking for?

library(tidyverse)
library(gtable)
library(grid)
library(gridExtra)
#> 
#> Attaching package: 'gridExtra'
#> The following object is masked from 'package:dplyr':
#> 
#>     combine

p1 <- mtcars %>%
  rownames_to_column() %>%
  filter(carb %in% c(1, 3, 6)) %>%
  ggplot(aes(x = disp, y = rowname)) +
  geom_point() +
  xlim(c(0, 450)) +
  facet_grid(carb ~ ., scales = "free_y", space = "free_y") +
  theme(panel.spacing = unit(1, 'lines'),
        strip.text.y = element_text(angle = 0))

gt1 <- ggplotGrob(p1)
panels <-c(subset(gt1$layout, grepl("panel", gt1$layout$name), se=t:r))
for(i in rev(panels$t-1)) {
  gt1 = gtable_add_rows(gt1, unit(0.5, "lines"), i)
}
panels <-c(subset(gt1$layout, grepl("panel", gt1$layout$name), se=t:r))
strips <- c(subset(gt1$layout, grepl("strip-r", gt1$layout$name), se=t:r))
stripText = gtable_filter(gt1, "strip-r")
for(i in 1:length(strips$t)) {
  gt1 = gtable_add_grob(gt1, stripText$grobs[[i]]$grobs[[1]], t=panels$t[i]-1, l=5)
}
gt1 = gt1[,-6]
for(i in panels$t) {
  gt1$heights[i-1] = unit(0.8, "lines")
  gt1$heights[i-2] = unit(0.2, "lines")
}

p2 <- mtcars %>%
  rownames_to_column() %>%
  filter(carb %in% c(2, 4, 8)) %>%
  ggplot(aes(x = disp, y = rowname)) +
  geom_point() +
  xlim(c(0, 450)) +
  facet_grid(carb ~ ., scales = "free_y", space = "free_y") +
  theme(panel.spacing = unit(1, 'lines'),
        strip.text.y = element_text(angle = 0))

gt2 <- ggplotGrob(p2)
#> Warning: Removed 2 rows containing missing values (geom_point).
panels <-c(subset(gt2$layout, grepl("panel", gt2$layout$name), se=t:r))
for(i in rev(panels$t-1)) {
  gt2 = gtable_add_rows(gt2, unit(0.5, "lines"), i)
}
panels <-c(subset(gt2$layout, grepl("panel", gt2$layout$name), se=t:r))
strips <- c(subset(gt2$layout, grepl("strip-r", gt2$layout$name), se=t:r))
stripText = gtable_filter(gt2, "strip-r")
for(i in 1:length(strips$t)) {
  gt2 = gtable_add_grob(gt2, stripText$grobs[[i]]$grobs[[1]], t=panels$t[i]-1, l=5)
}
gt2 = gt2[,-6]
for(i in panels$t) {
  gt2$heights[i-1] = unit(0.8, "lines")
  gt2$heights[i-2] = unit(0.2, "lines")
}

grid.arrange(gt1, gt2, ncol = 2)

Created on 2021-12-16 by the reprex package (v2.0.1)

If not, what changes need to be made?

jared_mamrot
  • 22,354
  • 4
  • 21
  • 46
  • Is it possible for all the facets to have equal spacing between rows (i.e., facets 6 and 8 both have one row but take up different amounts of space)? I realize doing so might lead to there being white space. – nateroe Dec 16 '21 at 03:08
  • I'm sure it's possible, but I've never done it before so I don't know the best way to approach it. If I have some spare time today I'll test out some ideas – jared_mamrot Dec 16 '21 at 21:45