Skip to content

Grouped boxplots that don't drop levels #3345

Closed
@ldecicco-USGS

Description

@ldecicco-USGS

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions