0

R noob here. I have been stumped on this graph all day and solutions like this and this this seem to hold my answer but I cannot get them to work for me.

I have a data frame that is a large version of the below sample which I am trying to plot using ggplot.

# create data
df <- data.frame(
  "ID" = rep(1:5, each = 4),
  "Date" = c(seq(as.Date("2019/09/18"), by = "day", length.out = 4), 
             seq(as.Date("2019/09/18"), by = "day", length.out = 4),
             seq(as.Date("2020/08/07"), by = "day", length.out = 4),
             seq(as.Date("2020/09/12"), by = "day", length.out = 4),
             seq(as.Date("2020/09/29"), by = "day", length.out = 4)),
  "MaxDepth" = round(runif(20, min = 10, max = 50), 1),
  "Trip" = rep(1:5, each = 4)
)

# plot using ggplot
ggplot(df, aes(Date, MaxDepth, col = factor(Trip))) + 
  geom_line() + 
  facet_grid(ID ~ format(Date, "%Y"), scales = "free_x") + 
  scale_y_reverse() + 
  scale_x_date(date_labels = "%b") + 
  labs(title = "Daily maximum depth\n", 
       x = "",
       y = "Depth [m]\n",
       col = "Fishing trip")

This turns out nicely as a two column, eleven row faceted graph with the fishing trips as colours.

However, it includes a lot of empty panels which I would like to avoid by creating a one column graph still with all eleven ID rows but that are separated by the same split label the two columns had. I.e. I would like the two individuals that were in the LHS 2019 plot to have that 2019 label on top, separated by the 2020 label from the other 9 individuals. Like in this mock up.

Hope this is clear. Please correct me or let me know what to improve for a better question. Grateful for any help! Even if those are suggestions that this is not a good way of representation or something like this is simply not possible. Thank you all!

  • Use `facet_wrap`: `facet_wrap(~ format(Date, "%Y") + ID, scales = "free_x", ncol = 1)`? And here is a similar post: https://stackoverflow.com/questions/51725106/how-to-remove-empty-facet-with-ggplot – mt1022 Apr 19 '21 at 11:42
  • Thank you for this suggestion. Unfortunately, this way a label for the year 2019/2020 gets created above each graph and those row labels (1-11) from the right hand side get drawn into the centre so that essentially the graph becomes unreadable. So far, I haven't been able to get the answers from the link you posted to work for me. However, I am quite surprised that it seems to be so difficult! – rapsberries Apr 19 '21 at 14:55
  • another work around is to draw a plot for year 2019 and another plot for year 2020, and then combine the two plot with R package `patchwork` or `cowplot`. – mt1022 Apr 19 '21 at 15:10

1 Answers1

0

Here is a possible way. I am not sure whether it works for your real data.

library(ggplot2)
library(patchwork)
library(dplyr)

plot_fun <- function(dtt){
    ggplot(dtt, aes(Date, MaxDepth, col = factor(Trip))) + 
        geom_line() + 
        facet_grid(ID ~ format(Date, "%Y"), scales = "free_x") + 
        scale_y_reverse() + 
        scale_x_date(date_labels = "%b") + 
        labs(x = NULL, y = NULL, col = "Fishing trip")
}

p1 <- plot_fun(df %>% filter(format(Date, '%Y') == '2019'))
p2 <- plot_fun(df %>% filter(format(Date, '%Y') == '2020'))

p1 / p2
ggsave('~/Downloads/test.png', width = 6, height = 6)

enter image description here

mt1022
  • 16,834
  • 5
  • 48
  • 71
  • Thank you so much for this possible solution, mt1022! It did work with my real data. However, just like in your example with the mock up data, the layout of the graphs doesn't fully match. Most importantly, I was hoping to share the x-axis between the two plots. However, multiple discussions suggest this feature doesn't (yet) exist for `patchwork`. At least `(p1 / p2) + plot_layout(guides = "collect") & scale_colour_discrete(limits = factor(min(range(df$Trip)):max(range(df$Trip)))) & theme(legend.position = "right")` combines the two legends into one. – rapsberries Apr 20 '21 at 19:24