3

I am creating a plot with multiple annotations, so I wrote a function to simplify that process. The ggplot() below shows the laborious annotate() commands for one "Szarkowski". Since I'm going to add multiple segments and text, I created the af function (also shown below). However, I throw a "cannot add ggproto objects together" error when using the function.

How do I create my annotation function properly?

Data

df<-structure(list(
  Department = structure(c(8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L), .Label = c("Architecture & Design", "Architecture & Design - Image Archive", 
    "Drawings & Prints", "Film", "Fluxus Collection", "Media and Performance", "Painting & Sculpture", "Photography"), class = "factor"), 
  Year = c(1970, 1967, 1960, 1960, 1960, 1960, 1970, 1970, 1970, 1970, 1970), 
  Gender2 = c("Female", "Female", "Female", "Female", "Female", "Female", "Female", "Female", "Female", "Female", "Female"), 
  Nationality2 = c(" American ", " American ", " American ", " American ", " American ", " American ", " American ", " American ", 
                               " American ", " American ", " American "), 
  YearDate = structure(c(20491200, -74203200, -295041600, -295041600, -295041600, -295041600, 20491200, 20491200, 20491200, 20491200, 20491200), class = c("POSIXct", "POSIXt"), tzone = ""), 
  American = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("American", "Not American"), class = "factor")), row.names = 5600:5610, class = "data.frame")

Here is my Annotation function:

af<-function(s_yr,e_yr,y_pos,lab){
  annotate(geom="point",x=as.POSIXct( as.Date(paste0(s_yr,"-01-01"))), y=y_pos,color='black',size=1)+
  annotate(geom="point",x=as.POSIXct( as.Date(paste0(e_yr,"-01-01"))), y=y_pos,color='black',size=1)+
  annotate(geom="segment",
       x=as.POSIXct( as.Date(paste0(s_yr,"-01-01"))), 
       xend=as.POSIXct( as.Date(paste0(e_yr,"-01-01"))),
       y=y_pos,yend=y_pos,color='black',size=1)+
  annotate(geom="text",x=as.POSIXct( as.Date(s_yr("-01-01"))), y=y_pos+20,color='black',size=3,label=lab)    }

Here is my ggplot() command, with the annotation function commented out

df %>%
ggplot(aes(YearDate,fill=Gender2))+geom_bar()+
  scale_fill_calc()+
  xlab("Date")+ylab("Count")+
  #Szarkowski annotation -- this hard coding works fine
  annotate(geom="point",x=as.POSIXct( as.Date("1962-01-01")), y=600,color='black',size=1)+
  annotate(geom="point",x=as.POSIXct( as.Date("1991-01-01")), y=600,color='black',size=1)+
  annotate(geom="segment",
           x=as.POSIXct( as.Date("1962-01-01")), 
           xend=as.POSIXct( as.Date("1991-01-01")),
       y=600,yend=600,color='black',size=1)+
  annotate(geom="text",x=as.POSIXct( as.Date("1978-01-01")), y=620,color='black',size=3,label="Szarkowski")+
  # cannot add `ggproto` objects together
  # af(1970,1990,777,"FakeLabel") +   # this line throws an error; how to fix `af` function?
  theme_minimal()
2
  • 6
    Instead of +'ing the annotations together, try putting them all in a list. The list method for +'ing to a ggplot2 adds every element of the list to a plot. E.g., in af() do list(annotate(...), annotate(...), ...). Commented Aug 26, 2021 at 17:54
  • Are you aware of an example you could share? Commented Aug 26, 2021 at 19:14

1 Answer 1

5

RE: comments

Here is what I mean exactly. Remove all the +es from the af() function and instead put all the annotations in a list. Putting components in a list does not only work for annotations, but can be convenient for recycling any number of plot components for multiple plots. This is due to the ggplot2:::ggplot_add.list() method that implicitly + es all the list elements to the plot.

library(ggplot2)

df<-structure(list(
  Department = structure(c(8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L), .Label = c("Architecture & Design", "Architecture & Design - Image Archive", 
    "Drawings & Prints", "Film", "Fluxus Collection", "Media and Performance", "Painting & Sculpture", "Photography"), class = "factor"), 
  Year = c(1970, 1967, 1960, 1960, 1960, 1960, 1970, 1970, 1970, 1970, 1970), 
  Gender2 = c("Female", "Female", "Female", "Female", "Female", "Female", "Female", "Female", "Female", "Female", "Female"), 
  Nationality2 = c(" American ", " American ", " American ", " American ", " American ", " American ", " American ", " American ", 
                               " American ", " American ", " American "), 
  YearDate = structure(c(20491200, -74203200, -295041600, -295041600, -295041600, -295041600, 20491200, 20491200, 20491200, 20491200, 20491200), class = c("POSIXct", "POSIXt"), tzone = ""), 
  American = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("American", "Not American"), class = "factor")), row.names = 5600:5610, class = "data.frame")

af<-function(s_yr,e_yr,y_pos,lab) {
  list(annotate(geom="point",
                x=as.POSIXct( as.Date(paste0(s_yr,"-01-01"))), 
                y=y_pos,color='black',size=1),
       annotate(geom="point",
                x=as.POSIXct( as.Date(paste0(e_yr,"-01-01"))), 
                y=y_pos,color='black',size=1),
       annotate(geom="segment",
                x=as.POSIXct( as.Date(paste0(s_yr,"-01-01"))), 
                xend=as.POSIXct( as.Date(paste0(e_yr,"-01-01"))),
                y=y_pos,yend=y_pos,color='black',size=1),
       annotate(geom="text",x=as.POSIXct( as.Date(paste0(s_yr, "-01-01"))), 
                y=y_pos+20,color='black',size=3,label=lab)   
  )
}

ggplot(df, aes(YearDate,fill=Gender2))+geom_bar()+
  # scale_fill_calc()+
  xlab("Date")+ylab("Count")+
  #Szarkowski annotation -- this hard coding works fine
  annotate(geom="point",x=as.POSIXct( as.Date("1962-01-01")), y=600,color='black',size=1)+
  annotate(geom="point",x=as.POSIXct( as.Date("1991-01-01")), y=600,color='black',size=1)+
  annotate(geom="segment",
           x=as.POSIXct( as.Date("1962-01-01")), 
           xend=as.POSIXct( as.Date("1991-01-01")),
           y=600,yend=600,color='black',size=1)+
  annotate(geom="text",x=as.POSIXct( as.Date("1978-01-01")), y=620,color='black',size=3,label="Szarkowski")+
  # cannot add `ggproto` objects together
  af(1970,1990,777,"FakeLabel") +
  theme_minimal()

Created on 2021-08-26 by the reprex package (v1.0.0)

Sign up to request clarification or add additional context in comments.

3 Comments

Hi Teunbrand, please suggest a solution here stackoverflow.com/q/68948902/2884859
Hi AnilGoyal, I don't see how the linked question is related to this questions or my answer. Can you clarify why I should suggest a solution there for other reasons than that the question is so far unanswered?
No that's not related. I just wanted to tag you, you being subject expert

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.