2

By default, facet_wrap will have trailing empty panels if the number of levels doesn't fill the grid. Can we switch it to leading empty panels? For example, in the minimal code below, I'd like the panel "a" to be alone in the first row instead of panel "g" being alone in the last.

Is there an easier way than hard coding every panel from a ggplotGrob object?

foo <- data.frame(x = rnorm(210), y = rnorm(210), z = letters[1:7])

ggplot(foo, aes(x = x, y = y)) +
  geom_point() +
  facet_wrap(~z)
tjebo
  • 21,977
  • 7
  • 58
  • 94
PerrySun
  • 187
  • 1
  • 1
  • 8
  • 4
    Look at this solution: [post](https://stackoverflow.com/questions/18337789/force-facet-wrap-to-fill-bottom-row-and-leave-any-gaps-in-the-top-row/18338240#18338240) – Johan Rosa Feb 03 '20 at 15:48
  • I do not see another approach. If you need help implementing that one, just let me know. – Johan Rosa Feb 03 '20 at 18:16
  • Does this answer your question? [Force facet\_wrap to fill bottom row (and leave any "gaps" in the top row)](https://stackoverflow.com/questions/18337789/force-facet-wrap-to-fill-bottom-row-and-leave-any-gaps-in-the-top-row) – Carlos Eduardo Lagosta Feb 04 '20 at 19:54
  • I have modified the title - hope this fits the purpose better and make the difference to the other post clearer – tjebo Feb 05 '20 at 09:25

1 Answers1

1

Not exactly using facet, but here another option of using the patchwork package, which gives you a very neat control of your plot panels.

Of course, this repeats all axes titles and labels, so that's probably not quite ideal. But an option.

library(tidyverse)
library(patchwork)

foo <- data.frame(x = rnorm(210), y = rnorm(210), z = letters[1:7])

list_plots <- map(.x = foo %>% group_split(z), .f = ~ ggplot(foo, aes(x = x, y = y)) +
      geom_point())

layout_p <- '
##A
BCD
EFG
'

wrap_plots(list_plots, design = layout_p)

Created on 2020-02-05 by the reprex package (v0.3.0)

A more programmatic approach would be to only need to set the number of rows, here in this example nrow = 2

nrow <- 2
# how many actual panels
n_panel <- length(unique(foo$z)) 
# calculate numbers of columns
ncol <- ifelse(n_panel %% nrow == 0, n_panel %/% nrow, n_panel %/% nrow+1)
# calculate number of leading empty panels
n_lead <- nrow*ncol - n_panel
# letters for the design argument in wrap_plots
plot_letters <- LETTERS[seq_along(unique(foo$z))]
# make a vector which can be cut into pieces of ncol length
x <- paste(c(rep('#',n_lead), plot_letters), collapse = '')
# cut into ncol pieces and add linebreaks
layout_l <- paste0('\n', substring(x, seq(1, nchar(x), ncol), seq(ncol, nchar(x), ncol)), collapse = '')

wrap_plots(list_plots, design = layout_l)

Created on 2020-02-05 by the reprex package (v0.3.0)

tjebo
  • 21,977
  • 7
  • 58
  • 94