Stacked time series plots are cool. Vastly superior to double y-axis plots which are a big no no according to graph theory. Exhibit A and Exhibit B. If Hadley Wickham is anti double y-axis plots then maybe you should be too? The core of the problem is that there is no objective way to scale the two y-axes, making it easy to suggest correlation when in fact there is none.
Enter stacked time series. I like them probably because I was indoctrinated early on in my Matlab/Oceanography days. The only downside is that they can take up more space on the page. But I think they’re the bees knees. So here’s a primer on creating stacked time series plots using the packages ggplot2 and gridExtra. I think of this as the brute force method. There is a cleaner way to do this by faceting in ggplot2, but we’ll leave that for a future post.
This is time series data courtesy of the National Estuarine Research Reserve. You can download the data here, but you’ll have to convert it to a csv file because WordPress only supports xls files.
library(ggplot2);library(scales);library(gridExtra) chinacamp<-read.csv("SFBCCWQ_2009.csv") chinacamp$rdate<-strptime(as.character(chinacamp$DateTimeStamp),"%m/%d/%Y%H:%M") #import date/time in POSIXlt format chinacamp2<-chinacamp[seq(1,nrow(chinacamp),4),]
So here, I’ve loaded the packages, then the data. I’ve created a new variable called “rdate” which will be in POSIXlt format. Then, I’ve created another dataframe using every fourth value because the original dataset was a bit longish at 35,000 rows. The new one is 8,760 rows. Don’t judge me, my laptop is old.
my.ylab = expression(paste("Temperature"," (",degree,"C)")) cc.temp<-ggplot(chinacamp2,aes(x=rdate,y=Temp))+geom_point(color="blue") +theme_bw()+ coord_cartesian(ylim=c(0,25))+labs(y=my.ylab)+ theme(axis.text.y=element_text(size=16),axis.title.y=element_text(size=18, vjust=1.2),axis.text.x=element_blank(),axis.title.x=element_blank(), panel.border = element_rect(size=.8, colour = "black"))+ scale_y_continuous(breaks=c(5,10,15,20,25))+ scale_x_datetime(breaks=date_breaks("2 month")) cc.temp
Here, I’ve gotten rid of the x-axis title and labels. That’s because we’re going to create more time series and stack them. Thusly…
cc.sal<-ggplot(chinacamp2,aes(x=rdate,y=Sal))+geom_point() +theme_bw()+ labs(y="psu")+scale_y_continuous(breaks=c(0,5,10,15,20,25,30))+theme( axis.text.y=element_text(size=16),axis.title.y=element_text(size=18, vjust=1.2), axis.text.x=element_blank(),axis.title.x=element_blank(), panel.border = element_rect(size=.8, colour = "black"))+ coord_cartesian(ylim=c(0,30))+ scale_x_datetime(breaks=date_breaks("2 month")) cc.sal cc.do<-ggplot(chinacamp2,aes(x=rdate,y=DO_mgl))+geom_point(color="red") +theme_bw()+ coord_cartesian(ylim=c(0,25))+labs(y="mg/L")+theme( axis.text.y=element_text(size=16),axis.title.y=element_text(size=18, vjust=1.2), axis.text.x=element_blank(),axis.title.x=element_blank(), panel.border = element_rect(size=.8, colour = "black"))+ scale_x_datetime(breaks=date_breaks("2 month")) cc.do cc.pH<-ggplot(chinacamp2,aes(x=rdate,y=pH))+geom_point(color="green") +theme_bw()+ coord_cartesian(ylim=c(7,9.5))+theme( axis.text.y=element_text(size=16),axis.title.y=element_text(size=16, vjust=1.2), axis.text.x=element_text(size=16),axis.title.x=element_text(size=18, vjust=-0.1), panel.border = element_rect(size=.8, colour = "black"))+labs(x="2009")+ scale_x_datetime(breaks=date_breaks("2 month"),labels=date_format("%b")) cc.pH
Note that we must create each plot as an object. Now we stitch them together!
ppi=300 png("awesome stacked time series.png",width=12*ppi, height=8*ppi, res=ppi) grid.arrange(cc.temp,cc.sal,cc.do,cc.pH, ncol=1) dev.off()
Ain’t she purty?? Just in case you were wondering, Wilson likes stacked time series too!