R tips and tricks: Producing smooth bitmap plots

Posted by Tom Moertel Sun, 26 Aug 2007 01:56:00 GMT

The R statistics system can produce first-class data visualizations, commonly known as plots. Internally, plots are represented in an abstract graphics format that can be rendered on any of R’s wide range of graphics “devices” to produce concrete output – windows, bitmap files, PostScript files, PDF files, and others.

The bitmap formats, such as PNG, are preferred for posting plots online because of their widespread support by web browsers. The default bitmap-rendering devices in R, unfortunately, produce graphics that look a little too “bitmapped” for modern web tastes. Here, for example, is a plot rendered by R’s “png” device:

Plot rendered via R's PNG device

There’s nothing technically wrong with the plot, but it looks out of place on a web page. That’s because modern web browsers use font-smoothing and anti-aliasing techniques to render just about everything else on the page. Against this clean, un-jagged backdrop, the oh-so-bitmapped plot looks like a throwback to a previous era.

Happily, we can produce clean, anti-aliased R plots with a little help. Here’s the earlier plot, anti-aliased:

Plot rendered via R's PDF device, then post-processed

To produce the anti-aliased plot, I used R to produce a PDF file. Then I rendered the PDF file into a PNG image at 300 dpi using Ghostscript. Finally, I scaled the 300-dpi image down to screen resolution, producing a high-quality, anti-aliased result.

Here’s the recipe in detail.

First, I define an R function called pdfit that takes an abstract graphics object and makes a PDF-file rendering of it, using my preferred graphics-device settings:

require("lattice")

pdfit <- function(f, ...) {
  trellis.device(dev=pdf, theme="col.whitebg", ...);
  print(f);
  dev.off()
}

Then, when I create a plot I want to publish, I use pdfit to render it into a PDF file:

P.img <- xyplot( subs.low + subs.high ~ date, ... )

pdfit(P.img, file="image-downloads.pdf")  # render plot into PDF file

Finally, I use Ghostscript and ImageMagick to convert the PDF file into a high-quality, anti-aliased PNG file. (I keep both formats: the PDF file is best for publishing in printed papers, and the PNG file is best for posting online.) I use a simple Makefile to automate the process of converting the PDF files into PNG files:

# Makefile (GNU make)

pdfs := $(wildcard *.pdf)
pngs := $(pdfs:.pdf=.png)

all: $(pngs)
.PHONY: all

%.png: %.pdf
    gs -dSAFTER -dBATCH -dNOPAUSE -sDEVICE=png16m \
       -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -r300 \
       -dBackgroundColor='16#ffffff' \
       -sOutputFile=$@ > /dev/null \
       $< && \
    mogrify -resize 500 $@

With this Makefile in my graphics directory, just a single “make” command is all it takes to convert my PDF images into anti-aliased PNG files, ready to post online.

And that’s it.

Do you have any tips or tricks for making good-looking graphics with R? If so, please do share.

Update: There is one downside to the sexy, anti-aliased plots: they are not as compressible as the old-style jagged plots. For the images above, for instance, the anti-aliased PNG file weighs in at 45 KB, but the original PNG file is a feathery 4.7 KB. So, if bandwidth is precious to you – or you’re planning on getting Slashdotted – you might want to stick with the jaggies.

Posted in
Tags , , , , ,
8 comments
no trackbacks
Reddit Delicious

Engauge Digitizer: a handy tool for extracting data from charts

Posted by Tom Moertel Tue, 17 Apr 2007 07:45:00 GMT

Today I wanted to extract the data that were visualized in a chart I saw on Seth Roberts’s blog. That is, I had a picture of a data set, and I wanted the numbers behind the picture.

This task turned out to be surprisingly easy – once I found Engauge Digitizer, an open-source (GPL) tool made for this very task. After I launched Engauge, the digitization process was straightforward:

  1. I established the chart’s coordinate system by clicking in the corners and entering the associated coordinates.
  2. Then I had Engauge identify data points. With the mouse, I selected a data point by hand, teaching Engauge what a point looks like. Then Engauge identified spots on chart that looked like data points and locked on to them. I was able to step through the points to tell Engauge to skip the few it misidentified.
  3. I manually selected a few more data points that were scrunched into blobs and had eluded Engauge’s point-detection heuristics.
  4. Finally, I exported the data set in CSV format.

If you ever need to extract the data behind a chart, do check out Engauge Digitizer. (If you use Fedora Linux, you’ll be happy to know that I have packaged Engauge for you. Get it at the RPMs section of the community site.)

Posted in
Tags , , , , , ,
no comments
no trackbacks
Reddit Delicious