@Cmrn_DP put together some code to make Matplotlib graphs that look like fivethirtyeight.com graphs. I see the attraction–fivethirtyeight graphs have a very simple, attractive look–but I’m not much of a Matplotlib user, so I took a few minutes to try and get the same style in Rs ggplot2 package. Here’s the result:
I’m pretty happy with it! There are however a couple of things I couldn’t really replicate. First, I didn’t play with fonts much. I like the 538 fonts, but I also like ggplot’s default font a heck of a lot (Helvetica? I’m not a font snob) so I just kept it. If you did want to change fonts, you would use “family=’Times'” or whatever in the style sections of the code below. I also didn’t try to replicate the box at the bottom of every 538 graph that has the site logo and the source of the data. This is really outside the scope of what ggplot can do.
Finally, I didn’t put a subtitle on the graph. Again, this is really difficult with ggplot but I have good news: you don’t want to do this anyways. The subtitle on 538 graphs is the result of a really frustrating design decision they made to not have axis labels on any of their graphs. Instead, the subtitle tells you what the y-axis is (the quantity being plotted), and the x-axis is designed to be self evident (usually a year or a date). Sure, having no axis labels makes the charts very attractive and minimalist, but it’s also kind of actively hostile to the viewer, so I tossed out the subtitle and included some actual axis labels.
The only other downside is that you have to tweak a lot of the values I have here if you want different resolutions, or to make your annotations show up in the right places for a different set of random data.
And here’s the code:
library(ggplot2) library(grid) line1<-rnorm(100,mean=15-seq(1,6,by=.05),sd=1) line2<-rnorm(100,mean=4+seq(1,21,by=.2),sd=.5) time<-seq(1,100,by=1) data<-data.frame(time,line1,line2) ggplot(data,aes(time)) + # The actual lines geom_line(aes(y=line1),size=1.6) + geom_line(aes(y=line2),size=1.6) + theme_bw() + # Set the entire chart region to a light gray color theme(panel.background=element_rect(fill="#F0F0F0")) + theme(plot.background=element_rect(fill="#F0F0F0")) + theme(panel.border=element_rect(colour="#F0F0F0")) + # Format the grid theme(panel.grid.major=element_line(colour="#D0D0D0",size=.75)) + scale_x_continuous(minor_breaks=0,breaks=seq(0,100,10),limits=c(0,100)) + scale_y_continuous(minor_breaks=0,breaks=seq(0,26,4),limits=c(0,25)) + theme(axis.ticks=element_blank()) + # Dispose of the legend theme(legend.position="none") + # Set title and axis labels, and format these and tick marks ggtitle("Some Random Data I Made") + theme(plot.title=element_text(face="bold",hjust=-.08,vjust=2,colour="#3C3C3C",size=20)) + ylab("Data Label") + xlab("Days Since Beginning") + theme(axis.text.x=element_text(size=11,colour="#535353",face="bold")) + theme(axis.text.y=element_text(size=11,colour="#535353",face="bold")) + theme(axis.title.y=element_text(size=11,colour="#535353",face="bold",vjust=1.5)) + theme(axis.title.x=element_text(size=11,colour="#535353",face="bold",vjust=-.5)) + # Big bold line at y=0 geom_hline(yintercept=0,size=1.2,colour="#535353") + # Plot margins and finally line annotations theme(plot.margin = unit(c(1, 1, .5, .7), "cm")) + annotate("text",x=14.7,y=15.3,label="Line 1",colour="#f8766d") + annotate("text",x=25,y=7.5,label="Line 2",colour="#00bdc4") ggsave(filename="/538.png",dpi=600)
Update: an earlier version of this displayed a low-res graph that looked crappy on high-res devices. Fixed this using ggsave, which I was previously unfamiliar with.