1
votes

Using ggplot2, I'm attempting to reorder a data representation with 3 factors: condition, sex, and time.

library(ggplot2)
library(dplyr)
DF <- data.frame(value = rnorm(100, 20, sd = 0.1),
                 cond = c(rep("a",25),rep("b",25),rep("a",25),rep("b",25)),
                 sex = c(rep("M",50),rep("F",50)),
                 time = rep(c("1","2"),50)
)
ggplot(data=DF, aes( x = time,
                     y = value,
                     fill = cond,
                     colour = sex,
)
) + 
  geom_boxplot(size = 1, outlier.shape = NA) +
  scale_fill_manual(values=c("#69b3a2", "#404080")) +
  scale_color_manual(values=c("grey10", "grey40")) +
  ggtitle("aF,aM,bF,bM") +
  theme(legend.position = "top")

Badly ordered plot. The way ggplot2 automatically orders condition first and interleaves sex poses the issue. It defaults to an interleaved "aF,aM,bF,bM" order regardless of which factor I assign to which aesthetic.

For analysis purposes, my preferred order is "aM,bM,aF,bF". Order sex first and interleave condition. I tried to fix it by converting the 2x2 factor assignments to one group with 4 levels, which gives me complete control over the order:

DF %>% mutate(grp = as.factor(paste0(cond,sex))) -> DF
level_order <- c("aM", "bM", "aF", "bF")

ggplot(data=DF, aes( x = time,
                     y = value,
                     fill = factor(grp, level=level_order),
                     colour = sex
)
) + 
  geom_boxplot(size = 1, outlier.shape = NA) +
  scale_fill_manual(values=c("#69b3a2", "#404080","#69b3a2", "#404080")) +
  scale_color_manual(values=c("grey10", "grey40", "grey40", "grey10")) +
  ggtitle("aM,bM,aF,bF") +
  theme(legend.position = "top")

Ordering OK, bad representation. However artificial grouping like this has its downsides, subjects are not assigned to a group, they are male/female (can't be changed) and assigned to some condition. Also the plot legend is unnecessarily cluttered, it has 6 keys instead of 4. It doesn't convey that it's 2x2 repeated measures design all that well.

I'm not sure if what I'm trying to do makes sense (I hope this isn't some massive brain fart), any help would be appreciated.

1
always worth to consider: facetstjebo

1 Answers

2
votes

The order in which you place the aesthetics controls the priority of its groupings. Thus if you switch the position of fill and colour you will get the result you are looking for (e.i. you want colour to be grouped first, and then fill)

ggplot(data=DF, aes( x = time,
                     y = value,
                     colour = sex,
                     fill = cond)) + 
  geom_boxplot(size = 1, outlier.shape = NA) +
  scale_fill_manual(values=c("#69b3a2", "#404080")) +
  scale_color_manual(values=c("grey10", "grey40")) +
  theme(legend.position = "top")