4

I would like to have grouped boxplots which whiskers is defined by stat_summary. With help of changing-whisker-definition I wrote the following code:

# Data
xdf2 <- data.frame(month = rep(1:6,each=100)
                  , grp = rep(c('A','B'), 50*6)
                  )
xdf2$m <- rpois(n=nrow(xdf2),10)
# Definition of whiskers
f <- function(x) {
  r <- quantile(x, probs = c(0.10, 0.25, 0.5, 0.75, 0.90))
  names(r) <- c("ymin", "lower", "middle", "upper", "ymax")
  r
}

# Add points outside of whiskers
o <- function(x) {
  subset(x, x < quantile(x,probs=0.1) | quantile(x,probs=0.9) < x)
}


# Plot
ggplot(data = xdf2
         , aes(factor(month),m, color=grp)
         ) +
       stat_summary(fun.data = f
                    , geom="boxplot"
                    , position=position_dodge(width=1)
                    , size=1
                    ) +
        stat_summary(fun.y = o, geom="point", position=position_dodge(width=1)) +
        scale_color_manual(values = c("gray30","darkgrey"),labels = c("AAA","BBB")) +
        theme_bw()

which gives the following graphs: enter image description here

There are some changes I would like to perform:

  • How can I change the width of the boxes?
  • How can I fill the boxes with the same color of the border?

I would be happy for any help. Thanks a lot.

Community
  • 1
  • 1
giordano
  • 2,954
  • 7
  • 35
  • 57
  • 1
    Check out [this question](https://stackoverflow.com/q/17479793/832693). Although it is for bar plots, using `width` in ggplot's `aes` worked for me for boxplots too. For some reason Google always landed me on this question first, probably because it is more recent. – Samuel Tan Jun 27 '17 at 13:43

1 Answers1

4

Map fill aesthetic to grp and add a similar scale for it. I'm using slightly different colours to make the mean visible.

To change boxplot widths, use ggsave with various width parameters, boxplots will be adjusted automatically. If you would like to add some space in between, you'll have to cheat a bit, see below.

It is not easy to modify width in conjunction with stat_summary: though there is a width parameter for geom_bar and geom_boxplot, I couldn't make it work properly with stat_summary. Instead, I'm using some dirty tricks with scale_x.

K <- length(unique(xdf2$month))
lev <- seq_len(1 + 2 * K)

xdf2$month2 <- factor(2 * xdf2$month, 
                      levels = lev)

ggplot(data = xdf2, aes(month2, m, color = grp, fill = grp)) +
  stat_summary(fun.data = f, geom="boxplot", 
               position=position_dodge(width=1.5), size=1) +
  stat_summary(fun.y = o, geom="point", position=position_dodge(width=1.5)) +
  scale_color_manual(values = c("gray30","darkgrey"),labels = c("AAA","BBB")) +
  scale_fill_manual(values = c("gray20","grey75"),labels = c("AAA","BBB")) +
  theme_bw() +
  scale_x_discrete(limits = lev, breaks = 1:K*2, labels = 1:K) 

enter image description here

Play around width in position_dodge for additional adjustment.

tonytonov
  • 25,060
  • 16
  • 82
  • 98
  • Thanks a lot!. Now I got nice boxplots. Regarding **width**: I want to make the width of the box narrower to show more distinction between month. – giordano Feb 06 '15 at 14:01
  • 1
    @giordano That was not as easy as I'd hoped. However, see the edit, I think it'll work for you. – tonytonov Feb 06 '15 at 15:09
  • Thank you very much. You were a great help. As I understand you create a factor with label 2*month and 13 levels. Maybe you can give me a hint why the box are narrower. – giordano Feb 06 '15 at 15:40
  • 1
    Well, the core of the trick is to create "invisible" factor levels and put them in between of existing ones, plus another two, leftmost and rightmost. These empty levels have no data, so no boxplots appear, which produces extra space. `labels` argument restores the original factor order. – tonytonov Feb 06 '15 at 16:26