48
votes

I would like to put perpendicular lines at the ends of the whiskers like the boxplot function automatically gives.

3
you can do this by calculating the quantile where ggplot draws the lines and drawing your own geom_segment or geom_crossbar. see this question - Justin
Is there some reason why this must be done in ggplot2, and not using boxplot which already does what you want, or is this question of purely academic interest...? - Jake Westfall
@Justin Thanks, I've checked out that question but it's too advanced for me and I keep getting errors, I don't know which bits to replace with what, sorry :/ - user1762299
@Jake It's purely aesthetic! I have an assignment requiring 2 graphs, one boxplot, one interaction graph. I've created the interaction graph in ggplot2, and would like the boxplot to be consistent (with the axes labels close up to the tick mark labels).... - user1762299
@Jake @ Justin Alternatively, is there a way I can move the position of the axes labels in base boxplot so that they are closer to the tick mark labels and in bold? I'm sure I'm being too pernickety, but I would like the graphs to be consistent. - user1762299

3 Answers

62
votes

As hinted but not implemented by @Roland, you can use stat_boxplot to implement this. The trick calling _boxplot twice and is to set the geom to errorbar for one of the calls.

Note that as R uses a pen and paper approach it is advisable to implement the error bars first the draw the traditional boxplot over the top.

Using @Roland's dummy data df

ggplot(df, aes(x=cond, y = value))  + 
 stat_boxplot(geom ='errorbar') + 
 geom_boxplot() # shorthand for  stat_boxplot(geom='boxplot')

enter image description here

The help for stat_boxplot (?stat_boxplot) detail the various values computed and saved in a data.frame

34
votes

To resize the whiskers lines we can use the argument width = 0.5 inside the function: stat_boxplot

set.seed(42)
df <- data.frame(cond = factor(rep(c("A", "B"), each = 500)), 
                 value = c(rnorm(500, mean = 1, sd = 0.2), 
                           rnorm(500, mean = 1.5, sd = 0.1))) 

library(ggplot2)
ggplot(df, aes(x = cond, y = value)) +
       stat_boxplot(geom = "errorbar", width = 0.5) +  
       geom_boxplot() 

enter image description here

7
votes

It might be possible to use stat_boxplot to calculate the whisker ends, but I am not enough of a ggplot2 wizard, so I use the base function for that.

set.seed(42)
df <- data.frame(cond = factor( rep(c("A","B"), each=500) ), 
                 value = c(rnorm(500,mean=1,sd=0.2),rnorm(500, mean=1.5,sd=0.1)))


whisk <- function(df,cond_col=1,val_col=2) {
  require(reshape2)
  condname <- names(df)[cond_col]
  names(df)[cond_col] <- "cond" 
  names(df)[val_col] <- "value"
  b <- boxplot(value~cond,data=df,plot=FALSE)
  df2 <- cbind(as.data.frame(b$stats),c("min","lq","m","uq","max"))
  names(df2) <- c(levels(df$cond),"pos")
  df2 <- melt(df2,id="pos",variable.name="cond")
  df2 <- dcast(df2,cond~pos)  
  names(df2)[1] <- condname
  df2
}



library(ggplot2)

plot1 <- ggplot(df, aes(x=cond)) 
plot1 <- plot1 + geom_errorbar(aes(ymin=min,ymax=max),data=whisk(df),width = 0.5)
plot1 <- plot1 + geom_boxplot(aes(y=value))
plot1

boxplot with horizontal at whisker ends