8

Like this previous poster, I am also using geom_text to annotate plots in gglot2. And I want to position those annotations in relative coordinates (proportion of facet H & W) rather than data coordinates. Easy enough for most plots, but in my case I'm dealing with histograms. I'm sure the relevant information as to the y scale must be lurking in the plot object somewhere (after adding geom_histogram), but I don't see where.

My question: How do I read maximum bar height from a faceted ggplot2 object containing geom_histogram? Can anyone help?

Community
  • 1
  • 1
Dave Braze
  • 441
  • 3
  • 14
  • You mean maximum bar height in data coordinates or in relative coordinates against the facet height? – kohske Oct 10 '12 at 21:25
  • Well, when I typed it I meant data coordinates. I could use that plus the expansion factor to get what I need to position the text geom. Is there a better way? – Dave Braze Oct 10 '12 at 21:41
  • If you want to make annotations at the top of bar in each facet, see my answer. Otherwise, could you please make things more clear, especially what you want to do finally? – kohske Oct 10 '12 at 21:45
  • Sorry for not being clear. I am wanting to annotate much like you show and your answer led me to what I needed. See comment below your answer. – Dave Braze Oct 10 '12 at 22:04

1 Answers1

5

Try this:

library(plyr)
library(scales)

p <- ggplot(mtcars, aes(mpg)) + geom_histogram(aes(y = ..density..)) + facet_wrap(~am)
r <- print(p)
# in data coordinate
(dc <- dlply(r$data[[1]], .(PANEL), function(x) max(x$density)))
(mx <- dlply(r$data[[1]], .(PANEL), function(x) x[which.max(x$density), ]$x))

# add annotation (see figure below)
p + geom_text(aes(x, y, label = text), 
  data = data.frame(x = unlist(mx), y = unlist(dc), text = LETTERS[1:2], am = 0:1),
  colour = "red", vjust = 0)


# scale range
(yr <- llply(r$panel$ranges, "[[", "y.range"))
# in relative coordinates
(rc <- mapply(function(d, y) rescale(d, from = y), dc, yr))

enter image description here

kohske
  • 65,572
  • 8
  • 165
  • 155
  • One piece I was missing was this (r <- print(p1)). Given that, I can do r$panel$ranges[[1]]$y.range – Dave Braze Oct 10 '12 at 21:54
  • Oops. Got distracted: One piece I was missing was this (r <- print(p1)). Given that, I can do (r$panel$ranges[[1]]$y.range) to get the yrange. I don't quite understand the ddply calls in your code (haven't worked with plyr much), but I'll play with it later. Do you see any obvious problem with directly accessing the y.range as I did here? – Dave Braze Oct 10 '12 at 22:00
  • If each facet has different y-range, then you need to get it for each facet. `r$panel$ranges[[1]]$y.range` only returns that of first facet. – kohske Oct 10 '12 at 22:03
  • Understood. I'm using fixed scales. Thanks! – Dave Braze Oct 10 '12 at 22:06
  • I can't see ranges or panels inside the ggplot object. I am not using facets. Is the solution different if there are no facets? @kohske – Lazarus Thurston Nov 14 '20 at 17:42