2
votes

My data take the structure of:

month <- c("May", "June", "July", "May", "June", "July")
year <- c("2015", "2015", "2015", "2016", "2016", "2016")
value <- c(1:3, 3:1)
df <- data.frame(month, year, value)

(The data actually go all the way from January to December for both years, this is just a short reproducible example.)

I'm doing a time series plot of value using ggplot (Assume I can't use plot.ts() for reasons which are too complicated to explain here). How do I layer the labels of the x axis, such that each tick mark is labeled with the month, but then below that there is another label below that with the year, so I get something like:

-------+-------+-------+----//---+-------+-------+-----
      May     June    July      May     June    July
              2015                      2016
2
You may have a look at stackoverflow.com/questions/20571306/… and stackoverflow.com/questions/18165863/… (I don't think they're duplicates). - Uwe
Thanks! That's just what I'm looking for. I had done a search but it did not bring those articles up. - mmyoung77
BTW: I prefer the ISO8601 standard naming of months 2015-05, 2015-06, 2015-07, 2016-05, etc. This ensures months are sorted in the proper order when converted to factor. - Uwe

2 Answers

5
votes

I would make not two axes but just one, with adjusted labels with a linebreak in them. The example shows how to add year below every month. I am used to only put year below january, if januari is not there the first month plotted of the year. You can adjust the preparation of the label to your own liking.

df$lab <- factor(1:6, labels = paste0(month,"\n",year))
ggplot(df, aes(x = lab, y = value)) + geom_point()

enter image description here

3
votes

Another option is to use faceting by year and put the facet labels below the x-axis labels. This makes it easier to have just one year label per year. I've removed the space between panels to create the appearance of an unfaceted plot, but added a vertical line between years to highlight the break in time. If you prefer separate panels, then just remove the panel.spacing and panel.border theme elements.

theme_set(theme_classic())

df$month = factor(df$month, levels=month.name)

ggplot(df, aes(x = month, y = value)) + 
  geom_point() +
  facet_grid(. ~ year, switch="x") +
  theme(strip.placement="outside",
        strip.background=element_rect(colour=NA),
        panel.spacing.x=unit(0,"lines"),
        panel.border=element_rect(colour="grey50", fill=NA))

enter image description here

Depending on your use case, you might find it preferable to use a color aesthetic for each year and put all the lines on a single panel:

ggplot(df, aes(x = month, y = value, colour=year, group=year)) + 
  geom_line() + geom_point() 

enter image description here