How to force facet_wrap to draw last panel in right bottom corner and leave the white gap

Viewed 83

I would like to force ggplot to draw the last graph in the right bottom corner and not the left one. I tried several things (similar questions here, here and here) but I don't manage to decide the order of the panels AND the position of the last plot.

This is the closest I managed to do: enter image description here

with this code:

data_1 <- data_hydro_NA %>%
  filter(Year >= "2000" & Station_river != "Var@Nice[Napo_3_aval]") %>%
  mutate(Plot_f = factor(Station_river, levels = c("Drac@Chabottes", "Durance@Oraison", "Var@Entrevaux", 
                                                   "Mareta@Vipiteno", "Roya@Breil_sur_Roya", "Var@Carros")))
plot_1 <- ggplot(data_1, aes(Date, Qm3s_norm, group = 1)) +
  geom_line(linetype = 1) + 
  facet_wrap(~ Plot_f) + 
  scale_x_date(name = "Years", limits = c(as.Date("2000-01-01"), as.Date("2021-01-01")), breaks = scales::breaks_pretty(n = 6)) +
  scale_y_continuous(name = expression("Daily discharge normalised by mean interannual discharge [m"^3/"s]")) 

data_2 <- data_hydro_NA %>%
  filter(Year >= "2000" & Station_river == "Var@Nice[Napo_3_aval]") %>%
  mutate(Plot_f = factor(Station_river, levels = c("Var@Nice[Napo_3_aval]")))

plot_2 <- ggplot(data_2, aes(Date, Qm3s_norm, group = 1)) +
  geom_line(linetype = 1) + 
  facet_wrap(~ Plot_f) + 
  scale_x_date(name = "Years", limits = c(as.Date("2000-01-01"), as.Date("2021-01-01")), breaks = scales::breaks_pretty(n = 6)) 

pushViewport(viewport(layout = grid.layout(3, 3)))
print(plot_1, vp = viewport(layout.pos.row = 1:2, layout.pos.col = 1:3))
print(plot_2, vp = viewport(layout.pos.row = 3, layout.pos.col = 3))

But as you can see the last plot doesn't have the same size as the others and it's not aligned (+ the axis labels but I guess that can be easily fixed).

I would like in fact that it looks more or less like this one, where the x and y labels are general in the figure, the 9th pannel is the same size as the others and it should be in the right bottom corner: enter image description here

Here's a small dput of my data for the structure (sorry I didn't know to make it even shorter):

structure(list(Station_code = c("Y6042010", "Y6042010", "Y6042010",  "Y6042010", "Y6042010", "Y6042010", "Y6042010", "Y6042010", "Y6042010",  "Y6042010", "Y6442015", "Y6442015", "Y6442015", "Y6442015", "Y6442015",  "Y6442015", "Y6442015", "Y6442015", "Y6442015", "Y6442015", "Y6442020",  "Y6442020", "Y6442020", "Y6442020", "Y6442020", "Y6442020", "Y6442020",  "Y6442020", "Y6442020", "Y6442020", "W2022030", "W2022030", "W2022030",  "W2022030", "W2022030", "W2022030", "W2022030", "W2022030", "W2022030",  "W2022030", "Y6624010", "Y6624010", "Y6624010", "Y6624010", "Y6624010",  "Y6624010", "Y6624010", "Y6624010", "Y6624010", "Y6624010", "36750PG",  "36750PG", "36750PG", "36750PG", "36750PG", "36750PG", "36750PG",  "36750PG", "36750PG", "36750PG"), Date = structure(c(17532, 17533,  17534, 17535, 17536, 17537, 17538, 17539, 17540, 17541, 17532,  17533, 17534, 17535, 17536, 17537, 17538, 17539, 17540, 17541,  17532, 17533, 17534, 17535, 17536, 17537, 17538, 17539, 17540,  17541, 17532, 17533, 17534, 17535, 17536, 17537, 17538, 17539,  17540, 17541, 17532, 17533, 17534, 17535, 17536, 17537, 17538, 17539, 17540, 17541, 17532, 17533, 17534, 17535, 17536, 17537,  17538, 17539, 17540, 17541), class = "Date"), Qm3s = c(6.69, 
6.03, 6.34, 10.9, 12.6, 10.1, 8.44, 11.2, 29.9, 17.9, 19.3, 17.7, 
17.4, 18.9, 23.9, 21.8, 20.2, 19.6, 114, 70.1, 19.7, 19.1, 18.2, 
22.3, 29.7, 26.5, 23.6, 25.3, 96.7, 54.9, 0.515, 0.521, 0.566, 
1.32, 1.53, 1.27, 1.36, 1.97, 3.44, 2.83, 4.3025, 5.04708333333333, 
4.15875, 4.64916666666667, 6.1025, 4.70083333333333, 4.48333333333333, 
6.8925, 42.3541666666667, 20.1833333333333, 2.10090909090909, 
2.02742424242424, 2.08424242424242, 2.12212121212121, 2.07333333333333, 
2.12151515151515, 2.09, 2.09242424242424, 2.96333333333333, 2.35757575757576 ), Year = c(2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L,  2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L,  2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L,  2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L,  2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L,  2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L), Month = c(1L,  1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,  1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,  1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,  1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Station_river = c("Var@Entrevaux",  "Var@Entrevaux", "Var@Entrevaux", "Var@Entrevaux", "Var@Entrevaux",  "Var@Entrevaux", "Var@Entrevaux", "Var@Entrevaux", "Var@Entrevaux",  "Var@Entrevaux", "Var@Nice[Napo_3_aval]", "Var@Nice[Napo_3_aval]",  "Var@Nice[Napo_3_aval]", "Var@Nice[Napo_3_aval]", "Var@Nice[Napo_3_aval]",  "Var@Nice[Napo_3_aval]", "Var@Nice[Napo_3_aval]", "Var@Nice[Napo_3_aval]",  "Var@Nice[Napo_3_aval]", "Var@Nice[Napo_3_aval]", "Var@Carros",  "Var@Carros", "Var@Carros", "Var@Carros", "Var@Carros", "Var@Carros",  "Var@Carros", "Var@Carros", "Var@Carros", "Var@Carros", "Drac@Chabottes",  "Drac@Chabottes", "Drac@Chabottes", "Drac@Chabottes", "Drac@Chabottes",  "Drac@Chabottes", "Drac@Chabottes", "Drac@Chabottes", "Drac@Chabottes",  "Drac@Chabottes", "Roya@Breil_sur_Roya", "Roya@Breil_sur_Roya",  "Roya@Breil_sur_Roya", "Roya@Breil_sur_Roya", "Roya@Breil_sur_Roya",  "Roya@Breil_sur_Roya", "Roya@Breil_sur_Roya", "Roya@Breil_sur_Roya",  "Roya@Breil_sur_Roya", "Roya@Breil_sur_Roya", "Mareta@Vipiteno",  "Mareta@Vipiteno", "Mareta@Vipiteno", "Mareta@Vipiteno", "Mareta@Vipiteno",  "Mareta@Vipiteno", "Mareta@Vipiteno", "Mareta@Vipiteno", "Mareta@Vipiteno",  "Mareta@Vipiteno")), row.names
= c(NA, -60L), groups = structure(list(
    Station_code = c("36750PG", "W2022030", "Y6042010", "Y6442015", 
    "Y6442020", "Y6624010"), Station_river = c("Mareta@Vipiteno", 
    "Drac@Chabottes", "Var@Entrevaux", "Var@Nice[Napo_3_aval]", 
    "Var@Carros", "Roya@Breil_sur_Roya"), .rows = structure(list(
        51:60, 31:40, 1:10, 11:20, 21:30, 41:50), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), row.names = c(NA, -6L), class = c("tbl_df",  "tbl", "data.frame"), .drop = TRUE), class = c("grouped_df",  "tbl_df", "tbl", "data.frame"))
1 Answers

I don't know a way to do this naturally with ggplot2 or extension packages. If there is a more straightforward way to do this, I'll gladly hear it. However, you can edit the gtable that your plot produces to get the result you want. For brevity (and because I couldn't run your code without errors), I simplified the example a bit, but it would probably work similarly for your plot. The example also assumes fixed x-axes.

First, we convert the plot to a gtable. We can inspect the row/column numbers with gtable::gtable_show_layout().

library(ggplot2)
library(grid)

df <- data.frame(
  x = 1:7, y = 1:7,
  facet = LETTERS[1:7]
)

g <- ggplot(df, aes(x, y)) +
  geom_point() +
  facet_wrap(~ facet)

gt <- ggplotGrob(g)
gtable::gtable_show_layout(gt)

In the layout above we need to figure out which cells we want to swap. We want to swap the 7th panel with the 9th (empty) panel. So, we find the cells that belong to these panels.

panel_7 <- which(gt$layout$l %in% 4:5 & gt$layout$t %in% 14:19)
panel_9 <- which(gt$layout$l %in% 12:13 & gt$layout$t %in% 14:19)

Then, we adjust the left (l) and right (r) positions of the grobs in these cells so that they are being swapped.

gt$layout$l[panel_7] <- gt$layout$l[panel_7] + 8
gt$layout$r[panel_7] <- gt$layout$r[panel_7] + 8
gt$layout$l[panel_9] <- gt$layout$l[panel_9] - 8
gt$layout$r[panel_9] <- gt$layout$r[panel_9] - 8

grid.newpage(); grid.draw(gt)

Created on 2021-04-01 by the reprex package (v1.0.0)

Related