Search code examples
rggplot2annotationsgeom-text

muddled annotated text on ggplot with facet


I want to add "A" for Fair and Good, "B" for Very good and Premium, and "C" for Ideal diamonds, but my texts are muddled.

library(dplyr; ggplot2)

Text for annotation

ann_text <- expand.grid(
  x  = c(1.5, 3.5, 5),
  y     = 6000,
  label = c("A", "B", "C"),
  clarity = c("I1", "SI2", "SI1", "VS2", "VS1", "VVS2", "VVS1", "IF"),
  cut = LETTERS[4:10])
) 

dummy df for the dots

price.avg <- diamonds %>%
  group_by(cut, color) %>%
  summarise(price = mean(price))

main plot

diamonds %>%
ggplot() +
geom_bar(aes(x = cut, fill = clarity)) +
facet_wrap(~ color) +
ylab("Count") +
  xlab("Cut") + 
  geom_point(data = price.avg, aes(x = cut, y = price, col = "")) +
    scale_y_continuous(sec.axis = sec_axis(~. * 1, name = "price")) +
    geom_vline(xintercept=c(2, 4) + .5, lwd=.5, colour="black") +
  geom_text(data = ann_text, aes(x = x, y = y, label = label))  +
  scale_color_manual(name = "", label = "Average price", values = "black") 

enter image description here

Thanks for any leads.


Solution

  • For an annotation dataframe, I guess you don't need to do expand.grid, just one row per label is fine. Therefore I used ann_text2 for label annotation. In the future if you want to avoid overlapping labels, use geom_text(check_overlap = TRUE).

    library(dplyr)
    library(ggplot2)
    
    ann_text2 <- data.frame(x = c(1.5, 3.5, 5),
                            y = 6000,
                            label = LETTERS[1:3])
    
    price.avg <- diamonds %>%
      group_by(cut, color) %>%
      summarise(price = mean(price))
    
    diamonds %>%
      ggplot() +
      geom_bar(aes(x = cut, fill = clarity)) +
      facet_wrap(~ color) +
      ylab("Count") +
      xlab("Cut") + 
      geom_point(data = price.avg, aes(x = cut, y = price, col = "")) +
      scale_y_continuous(sec.axis = sec_axis(~. * 1, name = "price")) +
      geom_vline(xintercept=c(2, 4) + .5, lwd=.5, colour="black") +
      geom_text(data = ann_text2, aes(x = x, y = y, label = label), check_overlap = T)  +
      scale_color_manual(name = "", label = "Average price", values = "black")