14

I am trying to plot the change in a time series for each calendar year using ggplot and I am having problems with the fine control of the x-axis. If I do not use scale="free_x" then I end up with an x-axis that shows several years as well as the year in question, like this:

Facet grid plot with common x-axis

If I do use scale="free_x" then as one would expect I end up with tick labels for each plot, and that in some cases vary by plot, which I do not want:

Facet grid plot with free x-axis

I have made various attempts to define the x-axis using scale_x_date etc but without any success. My question is therefore:

Q. How can I control the x-axis breaks and labels on a ggplot facet grid so that the (time series) x-axis is identical for each facet, shows only at the bottom of the panel and is in the form of months formatted 1, 2, 3 etc or as 'Jan','Feb','Mar'?

Code follows:

require(lubridate)
require(ggplot2)
require(plyr)

# generate data
df <- data.frame(date=seq(as.Date("2009/1/1"), by="day", length.out=1115),price=runif(1115, min=100, max=200))
# remove weekend days
df <- df[!(weekdays(as.Date(df$date)) %in% c('Saturday','Sunday')),]
# add some columns for later
df$year <- as.numeric(format(as.Date(df$date), format="%Y"))
df$month <- as.numeric(format(as.Date(df$date), format="%m"))
df$day <- as.numeric(format(as.Date(df$date), format="%d"))

# calculate change in price since the start of the calendar year
df <- ddply(df, .(year), transform, pctchg = ((price/price[1])-1))

p <- ggplot(df, aes(date, pctchg)) +
  geom_line( aes(group = 1, colour = pctchg),size=0.75) + 
  facet_wrap( ~ year, ncol = 2,scale="free_x") +
  scale_y_continuous(formatter = "percent") +
  opts(legend.position = "none")

print(p)
SlowLearner
  • 7,907
  • 11
  • 49
  • 80

1 Answers1

10

here is an example:

df <- transform(df, doy = as.Date(paste(2000, month, day, sep="/")))

p <- ggplot(df, aes(doy, pctchg)) +
 geom_line( aes(group = 1, colour = pctchg),size=0.75) + 
 facet_wrap( ~ year, ncol = 2) +
 scale_x_date(format = "%b") +
 scale_y_continuous(formatter = "percent") +
 opts(legend.position = "none")
p

enter image description here

Do you want this one?

The trick is to generate day of year of a same dummy year.

UPDATED

here is an example for the dev version (i.e., ggplot2 0.9)

p <- ggplot(df, aes(doy, pctchg)) +
  geom_line( aes(group = 1, colour = pctchg), size=0.75) + 
  facet_wrap( ~ year, ncol = 2) +
  scale_x_date(label = date_format("%b"), breaks = seq(min(df$doy), max(df$doy), "month")) +
  scale_y_continuous(label = percent_format()) +
  opts(legend.position = "none")
p

enter image description here

kohske
  • 65,572
  • 8
  • 165
  • 155
  • 1
    Sasu ga kohske. Simple and logical when you think about it and it works very well with my data. Might I also ask if there is any (straightforward way to make the breaks and labels go from Jan to Dec rather than going from Jan to Jan as in your screenshot above? I can live with the Jan to Jan, just wondering if there is a workaround. Thanks Dan – SlowLearner Jan 21 '12 at 10:21
  • Arigatou gozaimasu. That's probably not easy in the current version. – kohske Jan 21 '12 at 11:08
  • Intriguing, but also looks fairly different e.g. the formatter replacement percent_format() function. Hopefully backwards compatible! – SlowLearner Jan 21 '12 at 14:57