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:
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...
You could use annotation_custom
:
p_g + annotation_custom(p_v, xmin = 0, xmax = 50, ymin = 80, ymax = 150)
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"))))
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()