2

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"))
Jude
  • 153
  • 2
  • 8

1 Answers1

3

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)

teunbrand
  • 33,645
  • 4
  • 37
  • 63
  • That's perfect, thanks! I don't quite understand the link between the layout and the coordinates of the panel 7 and 9, are they not supposed to be (18, 5) and (18, 13)? I looked at the documentation on that function but it's not clear yet how these cordinates work. – Jude Apr 02 '21 at 09:05
  • Yes the main panels are indeed at those locations, but the corresponding axes and strips are in adjacent cells. You can essentially see the gtable as a matrix of locations. Every graphical object (grob) has indices for the left/top/right/bottom cells they appear in, but except for axis titles, they don't typically span more than 1 cell (so top == bottom and left == right most of the time). – teunbrand Apr 02 '21 at 09:39