6

I'll start with an MWE:

library(ggplot2)

p <- ggplot(mtcars, aes(factor(cyl), mpg, fill = factor(am)))
p + geom_boxplot()

enter image description here

I'd like to modify the colour of the whiskers, e.g., set it to red. I don't think it's possible to do this directly both geom_boxplot, so this is my workaround:

library(Hmisc)

stat_sum_df <- function(fun, geom = "crossbar", ...) {
  stat_summary(fun.data = fun, geom = geom, width = 0.4, ...)
}

p + stat_boxplot(geom = 'linerange', colour = "red", position = "dodge) +
    stat_sum_df("median_hilow", conf.int = 0.5, position = "dodge") 

enter image description here

The line ranges are stacked on top of each other. So next try:

p + stat_boxplot(geom = 'linerange', colour = "red", position = position_dodge(width = .5)) +
   stat_sum_df("median_hilow",conf.int=0.5, position = position_dodge(width = .5))

enter image description here

Looks nicer, but now there is a fixed space between the boxes (compare cyl = 8 on first and third plot). As I'm going to use this code for different number of levels of am (of course in my real data, it's not am), I don't know in advance how wide the boxes themselves will be, so I can't set a fixed width for the linerange without specifying a fixed width for the boxes.

Is there a way either to selectively modify whiskers of a boxplot or to adjust space between linerange elements according to space between the boxes?

zx8754
  • 52,746
  • 12
  • 114
  • 209
AnjaM
  • 2,941
  • 8
  • 39
  • 62
  • 1
    not exactly straightforward but one way could be to create two boxplots on top of each other. in one of them you remove whiskers and outliers (such that only the boxes are visible) and plot that over a second boxplot (that includes whiskers) for which you change the colour to red.. – erc Feb 27 '14 at 12:58

2 Answers2

8

How about plotting two boxplots on top of each other. One with red lines and a second one on top without any wiskers at all.

p + geom_boxplot(color="red") + geom_boxplot(aes(ymin=..lower.., ymax=..upper..)) 
shadow
  • 21,823
  • 4
  • 63
  • 77
  • Thanks, this works perfectly! Just a question: What do the dots in `..lower..` and `..upper..` mean? – AnjaM Feb 27 '14 at 14:37
  • 1
    The original data.frame does not actually have an column `lower`. This variable gets created in the `stat_boxplot` call. Variables that are created in ggplot stats can be used, you just have to add two dots before and after the name. Similar and often used is `geom_bin(aes(y = ..density..))`. – shadow Feb 27 '14 at 15:03
  • so smart! save my life! – maizer May 15 '19 at 15:38
8

Another option is to plot error bars and on top of them the boxplots without the whiskers:

library(ggplot)
p + stat_boxplot(
  geom = "errorbar",
  colour = "red",
  width = 0,
  position = position_dodge(0.75)
) +
  geom_boxplot(coef = 0, outlier.shape = NA)

enter image description here

mpalanco
  • 12,960
  • 2
  • 59
  • 67