'Adding shading alternate areas for categorical variable in a bar plot in ggplot2

I am trying t o plot a bar plot using ggplot2as follows:

library(ggplot2)
ggplot(mtcars, aes(factor(carb))) +
  geom_bar() +
  coord_flip()

enter image description here

x axis is a continous variable, while y axis is a categorical one (factor).

I would like to add alternate shading area behind each bar to differentiate the factors in y axis. I know I can use geom_rect() for this. How to calculate the y axis limits for the area, when it is a factor? x axis limits for the rectangles would be -Inf to Inf.

I am looking for something along the lines of this image, but for barplots instead of boxplots.

enter image description here



Solution 1:[1]

Solved it

# Create data.frame with shading info
shading <- data.frame(min = seq(from = 0.5, to = max(as.numeric(as.factor(mtcars$carb))), by = 1),
           max = seq(from = 1.5, to = max(as.numeric(as.factor(mtcars$carb))) + 0.5, by = 1),
           col = c(0,1))

# Plot
ggplot() +
  geom_bar(data = mtcars, mapping = aes(factor(carb))) +
  geom_rect(data = shading,
            aes(xmin = min, xmax = max, ymin = -Inf, ymax = Inf,
                fill = factor(col), alpha = 0.1)) +
  scale_fill_manual(values = c("white", "gray53")) +
  geom_bar(data = mtcars, mapping = aes(factor(carb))) +
  coord_flip() +
  guides(fill = FALSE, alpha = FALSE)

enter image description here

Solution 2:[2]

Perhaps something along these lines where you overlay the wider shaded bars, which vary in color, with the darker smaller bar?

ggplot(mtcars, aes(factor(carb))) +
  geom_bar(width = 1.1, aes(x = factor(carb), fill = ifelse(mtcars$carb %in% c(1,3,6), "blue", "transparent"))) +
  guides(fill = FALSE) +
  geom_bar(width = 0.7) +
  scale_fill_manual(values = c("transparent", "blue")) +
  coord_flip()

enter image description here

Solution 3:[3]

One can also use annotate with rect option to do a similar task:

ggplot(data = mtcars) +
  annotate('rect', xmin = c('1.5','3.5', '7'), xmax = c('2.5','4.5','8.5'), 
  ymin=-Inf, ymax=Inf, alpha=0.2, fill="red") +
  scale_fill_manual(values = c("white", "gray53")) +
  geom_bar(data = mtcars, mapping = aes(factor(carb))) +
  coord_flip() +
  scale_x_discrete(breaks=levels(factor(mtcars$carb))) + 
  guides(fill = "none", alpha = "none")

Here is the resulting graph:

enter image description here

Unfortunately, annotation regions overflow the bars. Could not find a way to correct this yet. Hope this helps if someone is looking for a similar solution.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Crops
Solution 2 lawyeR
Solution 3 MECoskun