Place annotation at the top of a series of histograms in ggplot2 using a for loop

I am creating a number of histograms and I want to add annotations towards the top of the graph. I am plotting these using a for loop so I need a way to place the annotations at the top even though my ylims change from graph to graph. If I could store the ylim for each graph within the loop I could cause the y coordinates for my annotation to vary based on the current graph. The y value I include in my annotation must change dynamically as the loop proceeds across iterations. Here is some sample code to demonstrate my issue (Notice how the annotation moves around. I need it to change based on the ylim for each graph):

library(ggplot2)

cuts <- levels(as.factor(diamonds$cut))

pdf(file = "Annotation Example.pdf", width = 11, height = 8,
    family = "Helvetica", bg = "white")

for (i in 1:length(cuts)) {
  by.cut<-subset(diamonds, diamonds$cut == cuts[[i]])
  print(ggplot(by.cut, aes(price)) +
    geom_histogram(fill = "steelblue", alpha = .55) +
  annotate ("text", label = "My annotation goes at the top", x = 10000 ,hjust = 0, y = 220, color = "darkred"))
}    
dev.off()

Answers


ggplot uses Inf in its positions to represent the extremes of the plot range, without changing the plot range. So the y value of the annotation can be set to Inf, and the vjust parameter can also be adjusted to get a better alignment.

...
print(ggplot(by.cut, aes(price)) +
      geom_histogram(fill = "steelblue", alpha = .55) +
      annotate("text", label = "My annotation goes at the top", 
               x = 10000, hjust = 0, y = Inf, vjust = 2, color = "darkred"))
...

For i<-2, this looks as:


There may be a neater way, but you can get the max count and use that to set y in the annotate call:

for (i in 1:length(cuts)) {

  by.cut<-subset(diamonds, diamonds$cut == cuts[[i]])

  ## get the cut points that ggplot will use. defaults to 30 bins and thus 29 cuts
  by.cut$cuts <- cut(by.cut$price, seq(min(by.cut$price), max(by.cut$price), length.out=29))

  ## get the highest count of prices in a given cut.
  y.max <- max(tapply(by.cut$price, by.cut$cuts, length))

  print(ggplot(by.cut, aes(price)) +
    geom_histogram(fill = "steelblue", alpha = .55) +
    ## change y = 220 to y = y.max as defined above
    annotate ("text", label = "My annotation goes at the top", x = 10000 ,hjust = 0, y = y.max, color = "darkred"))
}  

Need Your Help

(Scheme) Changing value in an array of booleans using a list

arrays boolean scheme racket bitvector

I need to make an array of booleans (0 or 1) with size 800000. I also need to be able to check/change the value at an index whenever I can. I cannot use vectors or the command set!.

Use Access replication id in form as number

forms ms-access ms-access-2007 guid ms-access-2010

I have a number of tables in an MS Access Db that have to use Replication IDs (GUID) as the primary key (and therefore also as foreign key contraints in the relationships between them). The data for