Reputation: 55340
Given an Existing plot object is it possible to add a layer UNDERNEATH an existing layer?
Example, in the graph below, is it possible to add geom_boxplot()
to P
such that the boxplot appears underneath geom_point()
?
## Starting from:
library(ggplot2)
P <- ggplot(data=dat, aes(x=id, y=val)) + geom_point()
## This adds boxplot, but obscures some of the points
P + geom_boxplot()
# Which is essentially
ggplot(data=dat, aes(x=id, y=val)) + geom_boxplot() + geom_point()
## However, this involves re-coding all of P (after the point insertion of the new layer).
## which is what I am hoping to avoid.
Bonus question: If there are multiple layers in the existing plot, is it possible to indicate where specifically to insert the new layer (with respect to the existing layers)?
set.seed(1)
N <- 100
id <- c("A", "B")
dat <- data.frame(id=sample(id, N, TRUE), val=rnorm(N))
Upvotes: 42
Views: 8555
Reputation: 15379
Expanding on Ricardo' answer, I use the following snippet:
library(ggplot2)
`-.gg` <- function(plot, layer) {
if (missing(layer)) {
stop("Cannot use `-.gg()` with a single argument. Did you accidentally put - on a new line?")
}
if (!is.ggplot(plot)) {
stop('Need a plot on the left side')
}
plot$layers = c(layer, plot$layers)
plot
}
As it allows you to:
P <- ggplot(data=dat, aes(x=id, y=val)) + geom_point()
P - geom_boxplot()
And the boxplot will be placed below the points.
Upvotes: 12
Reputation: 55340
Thanks @baptiste for pointing me in the right direction. To insert a layer underneath all other layers, just modify the layers
element of the plot object.
## For example:
P$layers <- c(geom_boxplot(), P$layers)
This handy little function inserts a layer at a designated z-level:
insertLayer <- function(P, after=0, ...) {
# P : Plot object
# after : Position where to insert new layers, relative to existing layers
# ... : additional layers, separated by commas (,) instead of plus sign (+)
if (after < 0)
after <- after + length(P$layers)
if (!length(P$layers))
P$layers <- list(...)
else
P$layers <- append(P$layers, list(...), after)
return(P)
}
Upvotes: 62