Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotate patchwork with line segments to create semantic plot relationships #216

Open
mattwarkentin opened this issue Nov 18, 2020 · 6 comments

Comments

@mattwarkentin
Copy link

mattwarkentin commented Nov 18, 2020

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):
Screen Shot 2020-11-18 at 4 55 17 PM

@thomasp85
Copy link
Owner

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 🙂

@mattwarkentin
Copy link
Author

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.

@thomasp85
Copy link
Owner

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

@mattwarkentin
Copy link
Author

mattwarkentin commented Dec 2, 2020

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")

@stoneyv
Copy link

stoneyv commented Aug 24, 2021

@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/

@japhir
Copy link

japhir commented Mar 25, 2024

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:

patchwork_annotation

I'd like to be able to draw segments that connect these different elements in the different plots.
patchwork_annotation_tweaked

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants