Monday, April 19, 2010

Example 7.33: Specifying fonts in graphics

For interactive data analysis, the default fonts used by SAS and R are acceptable, if not beautiful. However, for publication, it may be important to manipulate the fonts. For example, it would be desirable for the fonts in legends, axis labels, or other text printed in plots to approximate the typeface used in the rest of the text. Credit where it's due department: this blog entry is inspired by this blog post by Yihui Xie.

As an example plot, we'll revisit Figure 2.2 from the book, in which we plot MCS by CESD, with plot symbol showing substance abused.


In SAS, we'll focus on the "traditional" graphics most likely to be used for scientific publication. ODS graphics and the new SG procedures are currently difficult to customize.

There are several fonts supplied with the standard installation. However, any TrueType or Adobe Type 1 font on a local disk can be used. Making the fonts available requires a one-time use of proc fontreg.

proc fontreg mode=all;
fontpath "c:/windows/fonts";

In the above, the fontpath is the location in the operating system of the .ttf (TrueType) and/or .pfa/.pfb (Type 1) files.

Any font in that directory can then be used in SAS graphics, regardless of the format of the image file. Note however that this approach may mean that running your code on a different computer may alter the appearance of the graphic, since the fonts may not be available on another computer. If you anticipate needing to share the code, you can stick with the fonts SAS supplies, which are described in the online documentation: SAS Products; SAS/GRAPH; Concepts; Fonts.

The simplest way to make all text default to a desired font is to use the goptions statement (sections under 5.3).

goptions ftext="Comic Sans MS";

In Windows, the name of the font to put inside the quotation marks is displayed in the Explorer. If bold, italic, or bold italic is available, it can be requested by appending /bo, /it, or /bo/it to the font name, as demonstrated below.

Many statements in SAS/GRAPH accept a font= option, and these can be used to override the default font specified in the goptions statement.

In the example below, we use several different fonts to demonstrate how different statements specify fonts. In fact, the only plot elements in the assigned default Rockwell typeface are the y axis label and numbers and the labels of the symbols in the legend.

filename myurl
url ''

proc import datafile=myurl out=ds dbms=dlm;

goptions ftext = "Rockwell";

title font="Lucida Handwriting" "MCS by PCS with fonts";

mode=reserve position=(bottom center outside) across=3
label = (font= "Elephant" h=2 "Substance");

axis1 label=(font="Goudy Old Style" h=2 "The CESD axis")
value = ( h = 2 font= "Comic Sans MS") minor=none;

symbol1 font="Comic Sans MS" v='A' h=.7 c=black;
symbol2 font="Agency FB/bo" v='C' h=.7 c=black;
symbol3 font="Franklin Gothic Book/bo/it" v='H' h=.7;
proc gplot data=ds;
where female=1;
plot mcs*cesd=substance / legend=legend1 haxis=axis1;
run; quit;

The results, shown below, demonstrate the comic effects of reserving too much of the plot space for labels.


In R, the available fonts and the ways to use them varies by device. TrueType fonts can be displayed easily for the windows() device, and can similarly be used in publication graphics through the win.metafile() device (section 5.4.5).

windowsFonts(CS = windowsFont("Comic Sans MS"))

The windowsFonts() function would be called for each font to be included.

Unfortunately, the pdf() and postscript() devices most likely to be useful for publication using LaTeX do not appear to be able to read TrueType fonts, only Adobe Type 1 fonts. Some fonts can be purchased or downloaded for free in this format. If any reader has had success in using external fonts for these devices, I hope they'll provides code or links in the comments. There are some resources for converting TrueType to Type 1 freely available for *nix operating systems. However, for technical reasons, these conversions don't usually offer satisfying results.

Fortunately, R comes with several fonts for these devices. Their names can be easily displayed:

> names(pdfFonts())
[1] "serif" "sans"
[3] "mono" "AvantGarde"
[5] "Bookman" "Courier"
[7] "Helvetica" "Helvetica-Narrow"
[9] "NewCenturySchoolbook" "Palatino"
[11] "Times" "URWGothic"
[13] "URWBookman" "NimbusMon"
[15] "NimbusSan" "URWHelvetica"
[17] "NimbusSanCond" "CenturySch"
[19] "URWPalladio" "NimbusRom"
[21] "URWTimes" "Japan1"
[23] "Japan1HeiMin" "Japan1GothicBBB"
[25] "Japan1Ryumin" "Korea1"
[27] "Korea1deb" "CNS1"
[29] "GB1"

As with SAS, R offers both ways to change the default font (with the par() function) and fine control of individual options in specific function calls. R stores fonts in familys with names as listed above, and the (confusingly named) font which is an integer where 1 corresponds to plain text (the default), 2 to bold face, 3 to italic, 4 to bold italic, and 5 to the symbol font. Not all faces are necessarily available for all font families.

plot(cesd[female==1], mcs[female==1], type="n", bty="n", ylab="MCS",
xlab = '')
mcs[female==1&substance=="alcohol"],"A", family="AvantGarde", font=2)
mcs[female==1&substance=="cocaine"],"C", family="serif")
mcs[female==1&substance=="heroin"],"H", family="Courier", font=4)
title(xlab="This is the CESD axis", family="NewCenturySchoolbook", cex.lab=2)
title(family="Helvetica", font.main=3, cex.main=3, "MCS by CESD with fonts")

Similar to the SAS example, the only characters in the default Palatino font are the y axis label and the numerals.

Replicating a SAS legend appearing below the plot would be more difficult in R, as would replicating the default SAS legend that shows different plotted font characters.

No comments: