80

In this boxplot we can see the mean but how can we have also the number value on the plot for every mean of every box plot?

 ggplot(data=PlantGrowth, aes(x=group, y=weight, fill=group)) + geom_boxplot() +
     stat_summary(fun.y=mean, colour="darkred", geom="point", 
                           shape=18, size=3,show_guide = FALSE)

4 Answers4

104

First, you can calculate the group means with aggregate:

means <- aggregate(weight ~  group, PlantGrowth, mean)

This dataset can be used with geom_text:

library(ggplot2)
ggplot(data=PlantGrowth, aes(x=group, y=weight, fill=group)) + geom_boxplot() +
  stat_summary(fun=mean, colour="darkred", geom="point", 
               shape=18, size=3, show.legend=FALSE) + 
  geom_text(data = means, aes(label = weight, y = weight + 0.08))

Here, + 0.08 is used to place the label above the point representing the mean.

enter image description here


An alternative version without ggplot2:

means <- aggregate(weight ~  group, PlantGrowth, mean)

boxplot(weight ~ group, PlantGrowth)
points(1:3, means$weight, col = "red")
text(1:3, means$weight + 0.08, labels = means$weight)

enter image description here

stefan
  • 90,330
  • 6
  • 25
  • 51
Sven Hohenstein
  • 80,497
  • 17
  • 145
  • 168
38

You can use the output value from stat_summary()

ggplot(data=PlantGrowth, aes(x=group, y=weight, fill=group)) 
+ geom_boxplot() 
+ stat_summary(fun.y=mean, colour="darkred", geom="point", hape=18, size=3,show_guide = FALSE)
+ stat_summary(fun.y=mean, colour="red", geom="text", show_guide = FALSE, 
               vjust=-0.7, aes( label=round(..y.., digits=1)))
Pieter Meiresone
  • 1,910
  • 1
  • 22
  • 22
user3749036
  • 403
  • 4
  • 4
  • 1
    I also want to add mean in the boxplots. So, I amended by box plot code by adding `stat_summary()` & `fill=x` but getting this error: `Error: Unknown parameters: hape In addition: Warning message:show_guide has been deprecated. Please use show.legend instead. ` What's wrong in your code? – Aby Oct 06 '16 at 09:58
  • I like this answer, because it doesn't make a new table or write a new function, but instead uses a built-in feature of `ggplot2` in the way `ggplot2` was designed, imho, namely `fun.y=mean, ... , geom="text"`. I just had to put the `+` signs at the ends of lines instead of the beginnings, so there is that issue, but that's an easy and obvious fix. – jena Oct 20 '21 at 17:17
17

You can also use a function within stat_summary to calculate the mean and the hjust argument to place the text, you need a additional function but no additional data frame:

fun_mean <- function(x){
  return(data.frame(y=mean(x),label=mean(x,na.rm=T)))}


ggplot(PlantGrowth,aes(x=group,y=weight)) +
geom_boxplot(aes(fill=group)) +
stat_summary(fun.y = mean, geom="point",colour="darkred", size=3) +
stat_summary(fun.data = fun_mean, geom="text", vjust=-0.7)

enter image description here

mvogel
  • 359
  • 1
  • 3
6

The Magrittr way

I know there is an accepted answer already, but I wanted to show one cool way to do it in single command with the help of magrittr package.

PlantGrowth %$% # open dataset and make colnames accessible with '$'
split(weight,group) %T>% # split by group and side-pipe it into boxplot
boxplot %>% # plot
lapply(mean) %>% # data from split can still be used thanks to side-pipe '%T>%'
unlist %T>% # convert to atomic and side-pipe it to points
points(pch=18)  %>% # add points for means to the boxplot
text(x=.+0.06,labels=.) # use the values to print text

This code will produce a boxplot with means printed as points and values: boxplot with means

I split the command on multiple lines so I can comment on what each part does, but it can also be entered as a oneliner. You can learn more about this in my gist.

jena
  • 281
  • 4
  • 10