How to draw a grob on top of ggplot?

938 views Asked by At

I have a grob object (in my case it's euler plot) and a ggplot object, and I want to place one on top of another, for example:

library(eulerr)
library(ggplot2)

df <- data.frame(a=sample(100),b=sample(50:149), c=sample(20:119))
venn <- euler(list(
  A=df$a,
  B=df$b[1:50],
  C=df$c
), shape='ellipse')

p_v <- plot(venn, quantities = T, fills=c('red','green','blue'))
p_g <- ggplot(df, aes(x=a,y=b)) + geom_point()

# Now I want somehow to draw p_v on top of p_g
p_g + p_v

Should produce something like this: overlayed plot

I tried using ggplotify for example but couldn't find a way to get rid of white rectangle that was drawn as a canvas for the second plot...

1

There are 1 answers

8
Allan Cameron On BEST ANSWER

You could use annotation_custom:

p_g + annotation_custom(p_v, xmin  = 0, xmax = 50, ymin = 80, ymax = 150)

enter image description here

If you want this to work with log axis scales, you will need to use grid to directly draw p_v over p_g. You will first need to put it in a grobtree so that you can specify its position and dimensions:

p_g <- ggplot(df, aes(x=a,y=b)) + geom_point() + scale_y_log10()

p_g 
grid::grid.draw(
  grid::grobTree(p_v$children,
                 vp = grid::viewport(x = unit(0.3, "npc"), 
                                     y = unit(0.7, "npc"), 
                                     width = unit(0.4, "npc"), 
                                     height = unit(0.5, "npc"))))

enter image description here

If you want this as a single R object, you can do:

obj <- grid::grobTree(ggplotGrob(p_g), grid::grobTree(p_v$children,
                 vp = grid::viewport(x = unit(0.3, "npc"), 
                                     y = unit(0.7, "npc"), 
                                     width = unit(0.4, "npc"), 
                                     height = unit(0.5, "npc"))))

So that obj is now a grob of your whole picture.

One further way to do this would be using geom_grob from package ggpmisc:

library(ggpmisc)

ggplot(df, aes(x=a,y=b)) + 
  geom_point() + 
  geom_grob(aes(x = 12.5, y = 100, label = list(p_v$children$canvas.grob)),
            vp.width = 0.3, vp.height = 0.4) +
  scale_y_log10()

enter image description here