3

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
mmyoung77
  • 1,343
  • 3
  • 14
  • 22
  • 1
    You may have a look at http://stackoverflow.com/questions/20571306/multi-row-x-axis-labels-in-ggplot-line-chart and http://stackoverflow.com/questions/18165863/multirow-axis-labels-with-nested-grouping-variables (I don't think they're duplicates). – Uwe Jan 05 '17 at 21:58
  • Thanks! That's just what I'm looking for. I had done a search but it did not bring those articles up. – mmyoung77 Jan 05 '17 at 22:07
  • 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 Jan 05 '17 at 22:25

2 Answers2

5

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

Uwe
  • 41,420
  • 11
  • 90
  • 134
Wietze314
  • 5,942
  • 2
  • 21
  • 40
  • Very clever usage of the `label` parameter to the `factor()` function which enforces the given sort order. Simply using `paste()` without this would result in an alphabetical order of the labels June 2015, June 2016, July 2015, etc. thereby ignoring the years as primary sorting criteria. – Uwe Jan 05 '17 at 22:22
3

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

eipi10
  • 91,525
  • 24
  • 209
  • 285