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() P + ggtitle("Starting From Here") + xlab("") + ylab("") ggsave("~/P_initial.png", width=4.5, height=4.5) ## This adds boxplot, but obscures some of the points P + geom_boxplot() last_plot() + ggtitle("Incorrect Output") + xlab("") + ylab("") ggsave("~/P_wrong.png", width=4.5, height=4.5) ### Expected Output: # Which is essentially ggplot(data=dat, aes(x=id, y=val)) + geom_boxplot() + geom_point() last_plot() + ggtitle("Expected Output") + xlab("") + ylab("") ggsave("~/P_right.png", width=4.5, height=4.5) However, this involves re-coding all of P after the point insertion of the new layer. ---- 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)? ---- ### SAMPLE DATA set.seed(1) N <- 100 id <- c("A", "B") dat <- data.frame(id=sample(id, N, TRUE), val=rnorm(N)) ---- NOTE TO SELF: This has since been updated. See utilsRS. answer: insertLayer <- function(P, newLayer, at=1) { ## at: the index to the list wher newLayer will be inserted. ## if at == length(P$layers), then it is inserted one below the last layer ## if at > length(P$layers), then it is inserted as the top layer ## (though at that point, just use `+`) lis <- P$layers leng <- length(lis) # if strictly greater, insert at end if (at < 0) at <- (leng+at)+1 if (at == 0) stop("`at` cannot be 0. Did you mean `at=1`?") P$layers <- { if (at > leng) c(lis,newLayer) else if(at == 1) c(newLayer,lis) else c(lis[1:at-1], newLayer, lis[at:leng]) } return(P) } lis <- setNames(LETTERS[1:5], 1:5) lis 1 2 3 4 5 "A" "B" "C" "D" "E" -5 -4 -3 -2 -1