ggplot2 icon indicating copy to clipboard operation
ggplot2 copied to clipboard

Grouped boxplots that don't drop levels

Open ldecicco-USGS opened this issue 6 years ago • 11 comments

How do I (or...can I?) create a grouped boxplot in ggplot2 that does not drop the levels?

Here's an example:

df <- data.frame(x = rep(letters[1:2],6),
                 y = sample(100, size = 12),
                 type = rep(c("x","y","z"),4))

df2 <- df[!(df$x == "b" & df$type == "z"),]
df2$type <- factor(df2$type, levels = c("x","y","z"))

ggplot(data = df2) +
  geom_boxplot(aes(x=x,y=y, fill=type)) +
  scale_fill_discrete(drop=FALSE)

And what I get is: image

What I would like is for "b" to have a 3rd empty grouping for type "z". I have tried adding an empty row like this:

df3 <- rbind(df2, 
             data.frame(x = "b",
                        y = NA,
                        type = "z"))

df3$type <- factor(df3$type, levels = c("x","y","z"))

ggplot(data = df3) +
  geom_boxplot(aes(x=x,y=y, fill=type)) +
  scale_fill_discrete(drop=FALSE)

But I get the same result.

There's a solution from 2013 involving fake data and changing limits...but I was hoping to see if anything had improved since then that I've missed:

df4 <- rbind(df2, 
             data.frame(x = "b",
                        y = 1000,
                        type = "z"))

df4$type <- factor(df4$type, levels = c("x","y","z"))

ggplot(data = df4) +
  geom_boxplot(aes(x=x,y=y, fill=type)) +
  scale_fill_discrete(drop=FALSE) +
  coord_cartesian(ylim = range(df2$y))

This is good, but seems hacky: image

ldecicco-USGS avatar May 30 '19 21:05 ldecicco-USGS