shirewoman2
shirewoman2

Reputation: 1928

Add labels above top axis in ggplot2 graph while keeping original x axis on bottom

I'm trying to add some labels to a ggplot2 boxplot to indicate the number of observations, and I'd like that annotation to appear above the top axis of the graph. I can add them inside the graph pretty easily, and I suspect there's an application of ggplot_gtable that might do this, but I don't understand how to use that (a point in the direction of a good tutorial would be much appreciated). Here's some example data with labels:

Count <- sample(100:500, 3)
MyData <- data.frame(Category = c(rep("A", Count[1]), rep("B", Count[2]),
                                    rep("C", Count[3])),
                     Value = c(rnorm(Count[1], 10),
                               rnorm(Count[2], 20),
                               rnorm(Count[3], 30)))
MyCounts <- data.frame(Category = c("A", "B", "C"),
                       Count = Count)
MyCounts$Label <- paste("n =", MyCounts$Count)

ggplot(MyData, aes(x = Category, y = Value)) +
      geom_boxplot() +
      annotate("text", x = MyCounts$Category, y = 35, 
               label = MyCounts$Label)

boxplot with labels

What I'd love is for the "n = 441" and other labels to appear above the graph rather than just inside the upper boundary. Any suggestions?

Upvotes: 2

Views: 3489

Answers (1)

eipi10
eipi10

Reputation: 93761

Rather than separately calculating the counts, you can add the counts with geom_text and the original data frame (MyData). The key is that we need to add stat="count" inside geom_text so that counts will be calculated and can be used as the text labels.

theme_set(theme_classic())

ggplot(MyData, aes(x = Category, y = Value)) +
  geom_boxplot() +
  geom_text(stat="count", aes(label=paste0("n=",..count..)), y=1.05*max(MyData$Value)) +
  expand_limits(y=1.05*max(MyData$Value))

enter image description here

To put the labels above the plot, add some space above the plot area for the text labels and then use the code in the answer linked by @aosmith to override clipping:

library(grid)

theme_set(theme_bw())

p = ggplot(MyData, aes(x = Category, y = Value)) +
  geom_boxplot() +
  geom_text(stat="count", aes(label=paste0("n=",..count..)), 
            y=1.06*max(MyData$Value), size=5) +
  theme(plot.margin=margin(t=20))

# Override clipping
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)

enter image description here

Upvotes: 2

Related Questions