thomasp85 / patchwork

The Composer of ggplots
https://patchwork.data-imaginist.com
Other
2.46k stars 162 forks source link

Tagging fails when patching more than 2 nested patchwork #324

Closed hummuscience closed 1 year ago

hummuscience commented 1 year ago

I went with the example form the documentation.

library(ggplot2)
p1 <- ggplot(mtcars) + 
  geom_point(aes(mpg, disp)) 

p2 <- ggplot(mtcars) + 
  geom_boxplot(aes(gear, disp, group = gear)) 

p3 <- ggplot(mtcars) + 
  geom_point(aes(hp, wt, colour = mpg)) 

p4 <- ggplot(mtcars) + 
  geom_bar(aes(gear)) + 
  facet_wrap(~cyl)

p5 <- ggplot(mtcars) + 
  geom_bar(aes(vs)) + 
  facet_wrap(~cyl) 

The below works

(p1 + p2) / p3 +
  plot_annotation(tag_levels = 'A')

Screenshot from 2023-05-16 09-45-23

This doesn't

p1 |
  (p2 / p3) |
  (p4 / p5) +
  plot_annotation(tag_levels = 'A')

Screenshot from 2023-05-16 09-45-50

R version 4.3.0 (2023-04-21)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.6 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0 
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=de_DE.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=de_DE.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=de_DE.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=de_DE.UTF-8 LC_IDENTIFICATION=C       

time zone: Europe/Berlin
tzcode source: system (glibc)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] patchwork_1.1.2 ggplot2_3.4.2  

loaded via a namespace (and not attached):
 [1] labeling_0.4.2   utf8_1.2.3       R6_2.5.1         tidyselect_1.2.0
 [5] farver_2.1.1     magrittr_2.0.3   gtable_0.3.3     glue_1.6.2      
 [9] tibble_3.2.1     pkgconfig_2.0.3  generics_0.1.3   dplyr_1.1.2     
[13] lifecycle_1.0.3  cli_3.6.1        fansi_1.0.4      scales_1.2.1    
[17] grid_4.3.0       vctrs_0.6.2      withr_2.5.0      compiler_4.3.0  
[21] tools_4.3.0      munsell_0.5.0    pillar_1.9.0     colorspace_2.1-0
[25] rlang_1.1.1  
thomasp85 commented 1 year ago

This is a hard to debug issue with operator precedence. The plot_annotation() is added to the (p4/p5) rather than to the full plot because | has lower precedence than +. As plot_annotation()(for now) only have an effect on the top level patchwork it seems to vanish.

You can get the correct look by enclosing the whole assembly in parentheses before adding annotation:

library(ggplot2)
library(patchwork)

p1 <- ggplot(mtcars) + 
  geom_point(aes(mpg, disp)) 

p2 <- ggplot(mtcars) + 
  geom_boxplot(aes(gear, disp, group = gear)) 

p3 <- ggplot(mtcars) + 
  geom_point(aes(hp, wt, colour = mpg)) 

p4 <- ggplot(mtcars) + 
  geom_bar(aes(gear)) + 
  facet_wrap(~cyl)

p5 <- ggplot(mtcars) + 
  geom_bar(aes(vs)) + 
  facet_wrap(~cyl) 

(p1 |
  (p2 / p3) |
  (p4 / p5)) +
  plot_annotation(tag_levels = 'A')

Created on 2023-08-09 by the reprex package (v2.0.1)