dan
dan

Reputation: 6314

ggplot2 geom_boxplot side by side with facets

I have these data:

set.seed(1)
df <- data.frame(y=rnorm(12),name=factor(rep(c("a","a","b","b","c","c"),2),levels=c("a","b","c")),side=factor(rep(1:2,6),levels=1:2),group=factor(c(rep("x",6),rep("y",6)),levels=c("x","y")),stringsAsFactors=F)
df$upper <- df$y+0.1*df$y
df$lower <- df$y-0.1*df$y
df$max <- df$y+0.25*df$y
df$min <- df$y-0.25*df$y

And I'd like to ggplot-geom_boxplot them such that there are two facets, on top are df$group == x and at the bottom are df$group == y, where in each facet df$side == 1 appears to the left of df$side == 2. I also want to color df$group == x darkgray and df$group == y darkred.

Here's what I've tried:

library(ggplot2)
p <- ggplot(data=df,aes(name,color=group))+facet_wrap(~group,ncol=1)+scale_color_manual(values=c("darkgray","darkred"),labels=levels(df$group),name="group")+scale_fill_manual(values=c("darkgray","darkred"),labels=levels(df$group),name="group")
p <- p+geom_boxplot(aes(fill=group,lower=lower,upper=upper,middle=y,ymin=min,ymax=max),position=position_dodge(width=0),alpha=0.5,stat="identity")+theme(text=element_text(size=10))
p <- p+guides(fill=guide_legend(reverse=FALSE),colour=guide_legend(reverse=FALSE))

p gives me: enter image description here

which is close except for not having df$side == 1 to the left of df$side == 2.

Any idea how to do that?

Upvotes: 1

Views: 1344

Answers (1)

blmoore
blmoore

Reputation: 1487

I think this might be what you're after, it uses interaction to create a factor based on all combinations of the levels of its arguments (you could also use side:name):

ggplot(df, aes(x=name, group=interaction(side, name),
               col=group, fill=group)) +
    facet_wrap(~group) +
    geom_boxplot(aes(lower = lower, upper = upper,
      middle = y, ymin = min, ymax = max),
      position = position_dodge(width = 0.5),
      alpha = 0.5, stat = "identity")

enter image description here

It might be clearer to instead use colour to show which side is which, as the facets already label the group:

ggplot(df, aes(x=name, group=interaction(side, name),
               col=side, fill=side)) +
    facet_wrap(~group) +
    geom_boxplot(aes(lower = lower, upper = upper,
      middle = y, ymin = min, ymax = max),
      position = position_dodge(width = 0.5),
      alpha = 0.5, stat = "identity")

enter image description here

Upvotes: 1

Related Questions