23

One of my favorite tricks in base graphics is a pickup from Bill Dunlap. Being able to place numeric values (or any values) above bars in a bar plot (I don't use it but once in a while but love it).

mtcars2 <- mtcars[order(-mtcars$mpg), ]
par(cex.lab=1, cex.axis=.6, 
    mar=c(6.5, 3, 2, 2) + 0.1, xpd=NA) #shrink axis text and increas bot. mar.

barX <- barplot(mtcars2$mpg,xlab="Cars", main="MPG of Cars", 
   ylab="", names=rownames(mtcars2), mgp=c(5,1,0),
   ylim=c(0, 35), las=2, col=mtcars2$cyl)

mtext(side=2, text="MPG", cex=1, padj=-2.5)
text(cex=.5, x=barX, y=mtcars2$mpg+par("cxy")[2]/2, mtcars2$hp, xpd=TRUE) 

Which gives you:

enter image description here

I want to be able to do the same sort of annotation with faceted bar plots in ggplot. Obviously the values would also have to be by the same two variables you faceted to plot by so you could obtain them with ftable. I'd like to take the ftable results below (for non zero values) and place them above their respective bars.

library(ggplot2)
mtcars2 <- data.frame(id=1:nrow(mtcars), mtcars[, c(2, 8:11)])
mtcars2[, -1] <- lapply(mtcars2[, -1], as.factor)

with(mtcars2, ftable(cyl, gear, am))

ggplot(mtcars2, aes(x=cyl)) + geom_bar() + 
    facet_grid(gear~am)

This seems pretty difficult to me but maybe it'll be easier than I think. Thank you in advance for thinking about this problem.

Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519
  • Is this relevant? http://stackoverflow.com/a/9185168/1036500 – Ben Mar 22 '12 at 01:45
  • @ben I think you're on to the solution but I can't connect this to `facet_grid` – Tyler Rinker Mar 22 '12 at 01:58
  • Interestingly this kind of labeling is reckoned by some people to make the display more confusing and should be avoided: http://stackoverflow.com/q/6644997/1036500 and http://stackoverflow.com/a/9318468/1036500 – Ben Mar 22 '12 at 02:28

1 Answers1

24

Am I right in thinking that you just want the count (i.e the height) of each non-zero bar? If so, you can achieve that with

ggplot(mtcars2, aes(x=cyl)) + 
  geom_bar() + 
  facet_grid(gear~am) + 
  stat_bin(geom="text", aes(label=..count.., vjust=-1))

Which produces this graph (you may have to do some tweaking to get that highest label to show): enter image description here

count is a new variable in a dataframe created by stat_bin(), which is why you have to reference it with ..count..

Marius
  • 58,213
  • 16
  • 107
  • 105