1

Im aware of that thread, but the solution looks kinda long and complicated to me: Is there a quick and easy solution? To add the following vector under the y-axis?

yLabels <- c("","","n","mn","sd")

Reproducible data:

library(ggplot2)
library(magrittr)

mtcars <- mtcars

values <- rbind(tapply(mtcars$mpg,mtcars$gear,length)) %>% rbind(tapply(mtcars$mpg,mtcars$gear,mean)) %>% rbind(tapply(mtcars$mpg,mtcars$gear,sd)) %>%
  round(3)

levels <- rbind(levels(mtcars$gear%>%factor),matrix("",ncol=ncol(values)))

xlabs <- rbind(levels,values) %>% apply(.,2,function(x) {paste(x,collapse="\n")}) 
ggplot(mtcars, aes(x=factor(gear), y=mpg, fill=factor(gear))) + geom_boxplot() + scale_x_discrete(labels=xlabs)

This is what the above code processes:

Missing Labels to explain numerics

This is what i want: Labels under and "in line" with the y-axis. For n, mean and sd

enter image description here

Community
  • 1
  • 1
Andre Elrico
  • 10,956
  • 6
  • 50
  • 69
  • does this maybe help? http://stackoverflow.com/questions/12409960/ggplot2-annotate-outside-of-plot – drmariod Feb 06 '17 at 14:44
  • no it doesnt help – Andre Elrico Feb 06 '17 at 14:49
  • the codes i found need "specific" ylab positions (in my case maybe 8 etc..) i want a general solution to just paste (n,mn,sd) into that position. no matter what the scaling is. It already works with the xlabels. it a general approach. – Andre Elrico Feb 06 '17 at 14:57

2 Answers2

1

Not the nicest solution but gives you maybe an idea how to solve it in a general way...

xlabs <- c('2.5'='\n\nn\nmn\nsd', 
           rbind(levels,values) %>% apply(.,2,function(x) {paste(x,collapse="\n")})) 
ggplot(mtcars, aes(x=gear, y=mpg, fill=factor(gear))) + 
  geom_boxplot() + 
  scale_x_continuous(breaks=c(2.5,3,4,5), labels=xlabs) +
  theme(axis.ticks.x=element_line(color=c('white', rep('black', length(xlabs[-1])))))

I think a trick would be to use numeric values instead of the factor and you could add a tick label close to your limits. This one can than be labeled and the tick mark is white in the and...

Pretty hacky but I guess there is potential...

EDIT

Ok, a little bit more general in case of factors:

mtcars$test <- as.factor(mtcars$gear)
xlabs <- 
  c('2.5'='\n\nn\nmn\nsd', 
    rbind(levels,values) %>% 
      apply(.,2,function(x) {paste(x,collapse="\n")})) 

ggplot(mtcars, aes(x=as.numeric(test), y=mpg, fill=factor(gear))) + 
  geom_boxplot() + 
  scale_x_continuous(breaks=c(0.5, seq(1,length(levels(mtcars$test)))), 
                     labels=xlabs) +
  theme(axis.ticks.x=element_line(color=c('white', 
                                          rep('black', length(xlabs[-1])))))

Factors can be represented as.numeric and then these are basically integers starting at 1. So you can just use this to put them on the continuous scale and add an extra break at 0 or 0.5 and add your extra label to the xlabs variable. To hide the tick mark you can just add a white tick plus the number of levels in your column used for the x axis.

drmariod
  • 11,106
  • 16
  • 64
  • 110
  • this looks very good in this case!!! Now i need to find out how i can get the "2.5" automatically. How did you come up with 2.5 ? Trial and Error? – Andre Elrico Feb 06 '17 at 16:35
  • what should i use when groups are "categories" like "g1", "g2" and "g3". – Andre Elrico Feb 06 '17 at 16:38
  • Can give u an example tomorrow... But you can use as.numeric to convert your factors into a sequence starting at 1 so you can just at a break at 0.1 and this should work... – drmariod Feb 06 '17 at 17:51
  • would be great. I transformed the gears to a b and c. nothing works anymore: mtcars$gear[mtcars$gear==3] <- "a" mtcars$gear[mtcars$gear==4] <- "b" mtcars$gear[mtcars$gear==5] <- "c" – Andre Elrico Feb 06 '17 at 18:01
  • I added an example with factors... So here basically the factors have numbers starting at 1... Just add a break at .5 or 0 and modify the labels. If you have a lot labels this might overprint... But not sure how to solve this in a general way. – drmariod Feb 06 '17 at 19:47
  • thank you for taking the time. I believe i can construct a general solution with your very valuable input! I will post it here when its good and ready. – Andre Elrico Feb 07 '17 at 09:19
  • Would be nice if you could than except my answer :-) looking forward to a solid implementation – drmariod Feb 07 '17 at 09:23
0

With the valuable help of drmariod i came up with the following general solution:

1: the variable "xorigin" holds the x-value directly under the y-axis

2: met = metric-Variable , cat = categorial-Variable

library(ggplot2)
library(magrittr)

## Change only right sides to your needs ##
ds      <- diamonds
catName <- "cut"
metName <- "price"
###########################################

names(ds)[match(catName,names(ds))] <- "catVar"
names(ds)[match(metName,names(ds))] <- "metVar"

values <- rbind(tapply(ds$metVar,ds$catVar,length)) %>% rbind(tapply(ds$metVar,ds$catVar,mean)) %>% rbind(tapply(ds$metVar,ds$catVar,sd)) %>%
          round(3)
if (!is.factor(ds$catVar)) {
  ds$catVar <- factor(ds$catVar, levels=colnames(values))
}

levels <- rbind(levels(ds$catVar),matrix("",ncol=ncol(values)))

xlabs <- 
  c('2.5'='\n\nn\nmn\nsd', 
    rbind(levels,values) %>% 
      apply(.,2,function(x) {paste(x,collapse="\n")})) 

p <- ggplot(ds, aes(x=as.numeric(catVar), y=metVar, fill=factor(catVar))) + 
  geom_boxplot()
xorigin <- ggplot_build(p)$panel$ranges[[1]][[1]][1]
rm(p)


ggplot(ds, aes(x=as.numeric(catVar), y=metVar, fill=factor(catVar))) + 
  geom_boxplot() + 
  scale_x_continuous(breaks=c(xorigin, seq(1,length(levels(ds$catVar)))), 
                     labels=xlabs) +
  theme(axis.ticks.x=element_line(color=c('white', 
                                          rep('black', length(xlabs[-1]))))) +
  xlab(catName) +
  ylab(metName) +
  labs(fill=catName) 

enter image description here

Andre Elrico
  • 10,956
  • 6
  • 50
  • 69