10.04.2011

Post-Processing of R Graphs in Inkscape

In creating beautiful graphs for publication or public consumption, R sets the bar pretty high. There are somethings, however, that are not as easy to do with R. For example, a person might want to change the fonts, or move observation labels. While this can be accomplished in R, it is much easier to post-process graphs using third-party software such as Adobe Illustrator.

Inkscape is an  open-source graphics editor that has many of the same features as Adobe Illustrator. Inkscape uses the W3C standard Scalable Vector Graphics (SVG) file format. This format makes it easy to edit and manipulate text separate from the image as a whole. R also has support for saving plots in the SVG format.

The RSvgDevice package includes the function devSVG() to write graphics output to a SVG file. This function operates similarly to the pdf() or jpeg() functions. The dev.off() function is used to complete writing to the SVG file. An example is given below in which the studentized residuals from a regression of Zagat ratings on average price of a meal are plotted against the average cost of the meal. (You can get the data and codebook (MplsZagat) from the EPsy 8262 website here.)

library(car)
library(RSvgDevice)
 
# Fit linear model
model.zagat <- lm(Rating ~ Cost, data = zagat)
 
# Open SVG device
devSVG("/Users/zief0002/Desktop/restaurants.svg", height = 5, 
width = 6)
par(mfrow = c(1,1))
plot(x = zagat$Cost, y = rstandard(model.zagat),  
	xlab="Cost", 
	ylab="Studentized Residuals")
abline(h = 0)
abline(h = -2, lty = "dotted")
abline(h = 2, lty = "dotted")
text(x = zagat$Cost, y = rstandard(model.zagat), labels = zagat$Name, pos = 4)
 
# Turn off SVG device
dev.off()

The plot on the right is what is produced after running the R commands. This plot can then be post-processed using Inkscape. In this example, I have changed the font to Georgia, and rearranged many pf the text labels so that they don't overlap. I also increased the size of the font on the axes labels. You can see the difference between the plot that defaults from R and that same plot that has been post-processed in Inkscape (below).

In the example, the function devSVG() was used to write to the SVG file. The function svg() also works to write to a SVG file, but the text labels are not treated as text in this file. When I examined the XML code, it seems that this function was writing the text nodes as paths rather than text nodes.

One thing to note is that since the SVG file writes as XML, this means that the XML in the file needs to be well formed in order for Inkscape or a browser to open the file properly. For example, I had many ampersands (&) in the labels I used in the scatterplot because they existed in the data frame. These have to either be changed to "and" or the escaped unicode character of "&#038" can be used. (It is probably easier to just replce them with the word "and", then replace the ampersand in the label in Inkscape.)

SVG allows for the creation of interactive graphs as well. Deb Nolan and Duncan Temple-Lang have written the package SVGAnnotation (available on omegahat) that allows for features such as:
  • add tooltips,
  • add hyperlinks,
  • animate the plots,
  • implement simple linking,
  • add CSS information to an SVG document  
For example, rather than having the names of the restaurants on the plot (Sorry Mr. Tufte...I know it's plot clutter...sigh), the tooltips would allow the name of the restaurant to be displayed when hovering your mouse over the observation. You can read a great paper by Deb and Duncan about these features here.

No comments: