Вставить слой под существующими слоями в объект ggplot2

Учитывая существующий объект сюжета, можно добавить слой UNDERNEATH существующий слой?

Пример: на графике ниже можно добавить geom_boxplot() в P таким образом, чтобы полевая рамка отображалась под 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. 

Example Output


Бонусный вопрос: Если в существующем сюжете имеется несколько слоев, можно ли указать, где конкретно вставить новый слой (относительно существующих слоев)?


ДАННЫЕ ОБРАЗЦОВ

set.seed(1)
N <- 100
id <- c("A", "B")
dat <- data.frame(id=sample(id, N, TRUE), val=rnorm(N))

Ответы

Ответ 1

Спасибо @baptiste за то, что указали мне в правильном направлении. Чтобы вставить слой под все остальные слои, просто измените элемент layers объекта сюжета.

## For example:
P$layers <- c(geom_boxplot(), P$layers)

Ответ на вопрос о бонусе:

Эта удобная небольшая функция вставляет слой с заданным z-уровнем:

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)
    }

Ответ 2

Как показано в документации ggplot здесь, вы можете настроить объект ggplot скелета и добавить слои. Порядок, в котором вы указываете слои, - это порядок, в котором они будут отображаться на вашем участке.

Это даст вам ожидаемый результат:

ggplot() +
  geom_boxplot(data = dat, aes(x=id, y=val)) +
  geom_point(data = dat, aes(x=id, y=val)) 

Это приведет к неправильному выводу:

ggplot() +
  geom_point(data = dat, aes(x=id, y=val)) +
  geom_boxplot(data = dat, aes(x=id, y=val)) 

Я думаю, что это также ответит на ваш бонусный вопрос:)