Turns out you can do this with grid.path(...)
in grid
package. Read the documentation to see how to create a path with a hole in it.
library(gridExtra)
library(ggplot2)
ggp <- ggplot(mtcars, aes(mpg, wt)) + geom_point(size=3)
grid.newpage()
grid.draw(arrangeGrob(ggp))
grid.path(c(0,0,1,1,.48,.48,.62,.62),
c(0,1,1,0,.43,.50,.50,.43),
id=rep(1:2, each=4),
rule="evenodd",gp=gpar(fill="black", alpha=0.6))
NB: grid.draw(...)
and grid.path(...)
are in the grid
package; arrangeGrob(...)
is in the gridExtra
package. Loading gridExtra
causes grid
to be loaded. Thanks to @MartinBel for suggesting the edit.
In response to @BrandonBertelsen comment: grid.path(...)
is agnostic about shape; you just have to supply the coordinates.
center <- c(x=0.55,y=0.48)
r <- 0.1
circle <- do.call(rbind,lapply(seq(0,2*pi,length=36),
function(th)c(x=r*cos(th),y=r*sin(th))))
circle <- data.frame(circle)
circle$x <- circle$x + center["x"]
circle$y <- circle$y + center["y"]
ggp <- ggplot(mtcars, aes(mpg, wt)) + geom_point(size=3)
grid.newpage()
grid.draw(arrangeGrob(ggp))
grid.path(c(0,0,1,1,circle[,1]),
c(0,1,1,0,circle[,2]),
id=c(1,1,1,1,rep(2,nrow(circle))),
rule="evenodd",gp=gpar(fill="black", alpha=0.6))
The "circle" is an ellipse because of the plot window's aspect ratio.
Further reading: It’s Not What You Draw, It’s What You Don’t Draw by Paul Murrell in the R Journal