I am trying to get shaded rectangles on every even-numbered panel of my facet_wrap
plot. However, when I use geom_rect
, it produces the rectangles only on the second panel. I tried using annotate
and geom_tile
but with no success. I presume I am missing some simple detail here, probably related to the fact that my X variable is categorical and not numeric, but I am fighting this for a few hours already...
Here is my code:
even_numbers <- seq(2,nrow(df.plt),2)
ggplot(df.plt) +
geom_rect(data = df.plt[even_numbers, ],
xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) +
facet_wrap(vars(Grp), ncol=1)
And the resulting plot: resulting plot with geom_rect and facet_wrap not working as expected
Edit:
I have created a dummy dataset example which replicates my issue:
set.seed(002) # just to make it reproducible
df.tmp = data.frame(nst = rnorm(100*2), Srs = sample(rep(c("S3","S4"),100)), Cnd = sample(rep(c("DN","DA","DV","DAV"),50)), Grp = sample(rep(c("close","far"),100)))
even_numbers <- seq(2,nrow(df.tmp),2)
ggplot(df.tmp) +
geom_rect(data = df.tmp[even_numbers, ],
xmin = even_numbers - 0.5, xmax = even_numbers + 0.5,
ymin = -Inf, ymax = Inf, alpha = 0.3, fill = 'grey') +
geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) +
facet_wrap(vars(Grp), ncol=1)
While your idea was right IMHO you could achieve your desired result more easily by putting the xmin
and xmax
values in a dataframe and by mapping on aesthetics. First note that we only need a vector of even numbers of length(unique(df.tmp$Cnd))
, i.e. the number of categories of Cnd
. Second, as we are mixing discrete and continuous x variables I added an scale_x_discrete
before geom_rect
as otherwise we will get an error.
library(ggplot2)
even_numbers <- seq(2, length(unique(df.tmp$Cnd)), 2)
rects <- data.frame(
xmin = even_numbers - 0.5,
xmax = even_numbers + 0.5
)
ggplot(df.tmp) +
scale_x_discrete() +
geom_rect(
data = rects, aes(xmin = xmin, xmax = xmax),
ymin = -Inf, ymax = Inf, alpha = 0.3, fill = "grey"
) +
geom_boxplot(aes(x = Cnd, y = nst, fill = Srs), position = position_dodge(0.9), outlier.shape = 1) +
facet_wrap(vars(Grp), ncol = 1)
EDIT Just in case. The reason why your approach did not work is that the relevant part of the data used for the rects contains only the far
group. The issue is that basically only rects corresponding to even numbers in the range 1 to 4 (the number of Cnd
categories) are displayed. As can be seen from the following code snippet which replicates the data which under the hood is used for the rects in your approach only the far
grp is present (after filtering for even numbers in the range 1 to 4):
even_numbers <- seq(2,nrow(df.tmp),2)
dplyr::bind_cols(df.tmp[even_numbers, ], data.frame(even_number = even_numbers)) |>
dplyr::filter(even_number <= 4)
#> nst Srs Cnd Grp even_number
#> 1 0.1848492 S3 DV far 2
#> 2 -1.1303757 S3 DA far 4