Annotate patchwork with line segments to create semantic plot relationships
Hi @thomasp85,
I am wondering if it is currently possible to add line segments (such as those created with geom_segment(), for example) or any other ggplot annotations, on top of a patchwork to be able to create arbitrary relationships between plots. This could be useful for both standard patchworks or inset patchworks to create more obvious relationships between plots. Basically I'm trying to avoid doing any figure post-processing outside of R.
It is my understanding that the patchwork itself is a ggplot object, so I am wondering if this is possible, and if it isn't currently possible, if this feature is feasible. Maybe treating the full patchwork as having x and y dimensions of [0, 1] - so lines could somehow be drawn from and to arbitrary points on the patchwork. patchwork support for ggplot2::annotate() acting on the full patchwork would allow for some very flexible customization.
Here is an illustrative example for what I'm hoping to achieve (I'm hoping to be able to add the dashed lines to arbitrarily connect the subplots in a patchwork):

I agree that that would be very useful, but also non-trivial if at all possible. The reasons for this are pretty technical, but basically the different plots does not occupy a shared coordinate system and figuring out their relative locations are not straight-forward.
Don't hold your breath for it 🙂
I definitely do not have any of the technical knowledge to pretend to understand how patchwork or ggplot2 work internally, but would it be possible to "flatten" or rasterize the entire patchwork and then treat that as a single grob upon which additional annotations could be plotted?
Obviously vector graphics are preferred for various reasons. I'm just thinking out loud.
Sure, you can just treat it as one big canvas - that is already possible. But there is no way to reference any existing information in the plot so you'd have to position the lines through trial and error. I'd advice just doing it in illustrator/inkscape instead
Congrats on the CRAN release, Thomas. To follow-up on your above comment, could you point me in the right direction for doing what you described above? I don't actually mind a bit of trial-and-error as long as the end result is reproducible.
How does one "flatten" the patchwork into a single big canvas? I have tried using annotate() on a patchwork, but it seems to just add the annotation to the sub-plot canvases using the sub-plot coordinate systems. This would prohibit spanning annotations across/between plots.
library(magrittr)
library(ggplot2)
library(patchwork)
p1 <-
mtcars %>%
ggplot(aes(mpg, hp)) +
geom_point()
(p1 / p1) + annotate("text", 1, 1, label = "foo")

(p1 / p1) & annotate("text", 1, 1, label = "foo")

@mattwarkentin There is a simple example at the end of this documentation that will yield annotations between ggplots grobs in different viewports in a grid using the package gggrid. https://www.stat.auckland.ac.nz/~paul/Reports/gggrid/gggrid.html
gginards geom_debug(), ggpmisc https://docs.r4photobiology.info/gginnards/ https://docs.r4photobiology.info/ggpmisc/ https://pparacch.github.io/2017/09/25/plotting_in_R_ggplot2_part_5.html https://bookdown.org/rdpeng/RProgDA/the-grid-package.html
A great inspiration for visualizing relationships between data has been implemented by Susie Lu in d3-annotations d3js and react-annotations of the semiotic framework. https://react-annotation.susielu.com/
I recently ran into a similar issue (at least I think?) where I'd like to draw lines between subplots using both the subplot's coordinate systems.
For example:
library(ggplot2)
library(patchwork)
# let's say we have two sites a and b, where each has its own "depth" scale:
dat <- tibble::tibble(depth = 1:200, a = rnorm(length(depth)), b = rnorm(length(depth)))
# we can make a nice patchwork showing both (in this case the depth scale is identical but it could be very different)
(ggplot(dat) +
aes(x = depth, y = a) + geom_line() +
# where these vertical lines show which parts are related to which part of the other site
geom_vline(xintercept = c(0, 20, 30, 75, 150))) /
(ggplot(dat) +
aes(x = depth, y = b) + geom_line() +
# so here we get different values
geom_vline(xintercept = c(25, 50, 90, 120)))
ggsave("imgs/patchwork_annotation.png")
which results in the following image:
I'd like to be able to draw segments that connect these different elements in the different plots.
I think at present there is no way to draw geoms that take into account the x-axis values from both subplots, right? And hacking stuff together with grids itself seems to prefer relative units? So far I've had to do this kind of thing in Inkscape, which is a bit of a hassle if I need to update my figures.
I realize now that I shouldn't have drawn the vline at x = 0 for plot a, because it doesn't connect