Chapter 13: Graphics
Shih Chien University
2026-08-03
R plots graphics many ways; the book focuses on the three most popular packages:
This chapter: a tour of the common chart types, then graphics devices, then the full machinery of customization (par, low-level functions).
Our example data: 2008 cancer cases (American Cancer Society) and 2006 toxic releases by state (EPA), packaged as toxins.and.cancer:
plot is generic — vectors, tables, time series all plot. For two vectors, plot.default runs. Cancer death rate vs. toxin release rate:
| Argument | Description |
|---|---|
x, y |
data: two vectors, or a time series / formula / list / two-column matrix (see ?xy.coords) |
type |
"p" points, "l" lines, "o" overplotted, "b" both, "s" steps, "h" vertical lines, "n" nothing |
xlim / ylim |
axis limits |
log |
logarithmic axes: "", "x", "y", "xy" |
main / sub / xlab / ylab |
titles and axis labels |
ann / axes / frame.plot |
draw annotation / axes / surrounding box? |
panel.first / panel.last |
expressions evaluated before / after points are drawn |
asp |
aspect ratio y/x |
... |
graphical parameters (see below) |
A stronger correlation appears between airborne toxins and lung cancer:
locator(1) prints the coordinates of a clicked point; identify(x, y, labels) labels points as you click them.text does it (here resized with cex, repositioned with adj). The relationship is statistically significant (Chapter 18) — though that alone argues no causal story.Three relatives for special situations:
matplot(x, y, type=, lty=, lwd=, pch=, col=, cex=, ..., add=) plots all columns of one matrix against all columns of another; the usual par-style arguments accept vectors, one entry per series.smoothScatter shades regions by point density — the cure for overplotting with very many points (see Chapter 16).pairs draws a scatter plot matrix for every pair of variables:plot has a time-series method (plot.type = "multiple"/"single", panel, nc, yax.flip, margin controls…). The turkey prices of Chapter 7:
Strongly seasonal: November/December sales (Thanksgiving, Christmas), minor spring dips (Easter).
The autocorrelation function shows how correlated points are with their past, by lag — acf computes it and plots by default:
Correlated at 12-month cycles, inversely at 6-month cycles. (Time series analysis proper: Chapter 23.)
US doctoral degrees, 2001–2006 (Statistical Abstract), entered directly:
doctorates <- data.frame(
year=c(2001, 2002, 2003, 2004, 2005, 2006),
engineering=c(5323, 5511, 5079, 5280, 5777, 6425),
science=c(20643, 20017, 19529, 20001, 20498, 21564),
education=c(6436, 6349, 6503, 6643, 6635, 6226),
health=c(1591, 1541, 1654, 1633, 1720, 1785),
humanities=c(5213, 5178, 5051, 5020, 5013, 4949),
other=c(2159, 2141, 2209, 2180, 2480, 2436))
doctorates.m <- as.matrix(doctorates[2:7]) # barplot wants a matrix,
rownames(doctorates.m) <- doctorates[, 1] # not a data frame
barplot(doctorates.m[1, ])Default behavior: y-axis drawn, no x-axis line, bars named from column names.
Side-by-side horizontal bars with a legend; then stacked columns (transpose so columns = years, widen ylim to fit the legend):
Key arguments (of many):
| Argument | Description |
|---|---|
height |
vector, or matrix (stacked if beside=FALSE, grouped if TRUE) |
width / space |
bar widths / gaps (with beside=TRUE: c(within, between) groups) |
names.arg / legend.text |
bar labels / legend (logical = use rownames) |
beside / horiz |
grouped vs. stacked / horizontal vs. vertical |
density / angle |
shading lines per inch / their slope |
col / border |
bar colors / border color |
main, sub, xlab, ylab, xlim, ylim, log, axes |
the usual annotations |
xpd |
may bars overflow the plot region? |
cex.axis / cex.names / axisnames / axis.lty |
axis text sizing and styling |
inside / offset / add / args.legend |
separators, baseline shift, overplot, legend options |
What happened to US-caught fish in 2006 (millions of pounds):
Arguments: x (nonnegative values), labels, edges (polygon smoothness), radius, clockwise + init.angle, density/angle shading, col (default: six pastels), border, lty, main.
Warning
The help file itself says it: “Pie charts are a very bad way of displaying information. The eye is good at judging linear measures and bad at judging relative areas. A bar chart or dot chart is a preferable way of displaying this type of data.”
How does a categorical outcome vary along a numeric axis? cdplot smooths with kernel density estimates (density underneath; arguments bw, n, from, to pass through; ylevels reorders; formula+data+subset supported). Batting hand by batting average:
The proportion of switch hitters (B) rises with batting average.
For two factors, three displays of the contingency structure:
mosaicplot boxes are proportional to counts; further arguments: sort, off (spacing), dir (orientations), shade (extended plots coloring log-linear residuals), margin, type ("pearson"/"deviance"/"FT" residuals).spineplot(bats~throws, data=...) — the close sibling.assocplot(table(bats, throws)) — bars showing each cell’s deviation from independence (Cohen–Friendly).stars and fourfoldplot.All 3-D functions plot a matrix: row index = x, column index = y, cell = z. The book’s example: USGS elevation data for Yosemite Valley, downloaded as GridFloat (a 562×253 stream of 4-byte floats read with readBin(..., size=4, endian="little"), then given dim); packaged as yosemite:
Key arguments: x/y (coordinates of rows/columns), z (the matrix), theta/phi (viewing azimuth/colatitude), r/d (viewpoint distance, perspective strength), expand (z exaggeration), col/border, ltheta/lphi (light source), shade, box/axes/nticks/ticktype.
Looking toward Half Dome — flip the columns (persp draws y bottom-up), take a square 253-column subset (mind the fencepost +1!), rotate and light:
image color-codes the matrix as a grid (arguments: zlim, col — typically heat.colors, topo.colors, terrain.colors, breaks, oldstyle, add):
(Tweaks: aspect ratio matching the data, reversed y, a 33-step gray ramp (0:32)/32.) The biology-flavored relative heatmap adds optional dendrograms along the margins — Rowv/Colv, distfun/hclustfun, scale, margins, cexRow/cexCol and friends.
contour joins equal values with lines — arguments nlevels/levels, labels/labcex/drawlabels/method (label placement: "simple", "edge", "flattest"), vfont, plus the usual col/lty/lwd/add:
Contours are commonly added to an image plot (add=TRUE).
Plate appearances (PA = AB+BB+HBP+SF+SH) per batter, 2008:
A horde of sub-50-PA players — worth excluding from rate statistics. Zoom in and refine the bins:
Many statisticians prefer density plots — more robust, easier to read. Compute with density, draw with plot, garnish with a rug (a strip plot along the axis):
A Q-Q plot charts sample quantiles against theoretical ones — points on the 45° diagonal mean the distributions match. qqnorm compares against the normal; qqplot compares two arbitrary distributions:
At-bats are decidedly not normal — the bowed shape says it instantly.
A box plot compacts a distribution: box = interquartile range (25th–75th percentile), inner line = median, whiskers = adjacent values (largest observation ≤ Q3 + 1.5·IQR; smallest ≥ Q1 − 1.5·IQR), loose points = outside values.
Key boxplot arguments: formula y~grp + data + subset (or vectors directly); range (whisker reach), width/varwidth (∝ √n), notch (±1.58·IQR/√n intervals), outline, names, plot (FALSE returns statistics), border/col, log, horizontal, add, at, pars.
On-base percentage by American League team, regulars only:
Graphics land on a device. Defaults by platform: windows (Windows), X11 (Unix), quartz (macOS). File devices: bmp, jpeg, png, tiff, plus postscript, pdf, pictex (LaTeX), xfig, bitmap.
width, height, pointsize; file devices take a file argument. (Pedantically filename for bmp/jpeg/png/tiff — but partial matching lets file work everywhere.)dev.off() to actually write the file. The book’s own figures were produced exactly this way:Customize via (1) arguments to charting functions, (2) session parameters (par), (3) functions that modify an existing chart, or (4) writing your own functions. Arguments most chart functions share: add, axes, log, type, xlab/ylab, main, sub.
par queries and sets parameters on the active device — set once, affect every subsequent plot:
All parameters are read-write except the read-only cin, cra, csi, cxy, din. Caution: some functions reuse parameter names with different meanings (e.g., bg in points = point background).
mai (inches) / mar (text lines, default c(5.1, 4.1, 4.1, 2.1) for bottom/left/top/right) / mex (line-size factor); title-label spacing via mgp; device size via read-only din; square plot region via pty="s".mfcol=c(3,2) (fill by column) or mfrow (by row) split the device; mfg jumps to a chosen cell. Outer margins: omi/oma/omd. Per-figure geometry: pin, plt, fig. Clipping: xpd.(Easier alternatives: layout, split.screen — or the grid/lattice packages.)
ps (point size) × cex (global scale) × cex.axis/cex.lab/cex.main/cex.sub. Typeface: family; style via font (+ .axis, .lab, .main, .sub). Alignment adj, line spacing lheight, rotation crt (characters) / srt (strings).lty (0=blank, 1=solid, 2=dashed, 3=dotted, 4=dotdash, 5=longdash, 6=twodash), width lwd, ends lend, joins ljoin/lmitre; plot box style bty ("o", "l", "7", "]", "c", "u", "n").bg, fg, col (+ .axis, .lab, .main, .sub). Specify by name (colors()), "#RRGGBB", or palette index (palette()); generators: rgb, hsv, hcl, gray, rainbow.lab (tick counts), las (label orientation), mgp, tick sizes tcl/tck, tick positions xaxp/yaxp, interval style xaxs/yaxs ("r" extends 4%, "i" internal), suppress with xaxt="n"/yaxt="n"; log flags xlog/ylog.pch (19 solid circle, 20 bullet, 21 filled circle, 22 square, 23 diamond, 24/25 triangles; see ?points); symbol size historically mkh.ann (annotation on/off), ask (prompt before new page), new (overplot pretender), usr (user-coordinate extremes), smo, err.High-level functions are assembled from low-level ones — plot calls title, plot.new, plot.window, points, lines, axis, box; pie calls polygon, lines, text, title; boxplot delegates to bxp; and so on. Knowing the low level means you can pass customization through the high level, or build charts from scratch.
points(x, y, type="p", ...) — add points (useful: col, bg, pch, cex, lwd); matrix version matpoints.lines(x, y, ...) — add connected segments (useful: lty, lwd, col, lend, ljoin, lmitre); matrix version matlines.curve(expr, from, to, n=101, add=, ...) — plot an expression in x or a function name.abline draws one line across the plot — by intercept+slope (a, b), horizontal (h), vertical (v), regression object (reg), or coef; untf un-transforms on log axes:
Vector arguments draw many lines at once (abline(h=1:10, v=1:10)) — though for a grid, use grid(nx, ny, col, lty, lwd). Shapes: polygon(x, y, density, angle, border, col, lty); rectangles via rect(xleft, ybottom, xright, ytop, ...); point-pair segments via segments(x0, y0, x1, y1, ...); arrows via arrows.
text(x, y, labels, adj, pos, offset, vfont, cex, col, font) — text at coordinates (pos: 1 below, 2 left, 3 above, 4 right).mtext(text, side=3, line=0, outer=, at=, ...) — text in a margin (sides 1–4 = bottom/left/top/right).title(main, sub, xlab, ylab, line=, outer=) — annotate after the fact.legend(x, y, legend, ...) — the kitchen sink: fill (color boxes), col/lty/lwd/pch (sample lines/points), bty/bg/box.* (the legend box), pt.bg/pt.cex/pt.lwd, xjust/yjust, x.intersp/y.intersp/adj/text.width/text.col, merge, ncol/horiz, title, inset, xpd.axis(side, at, labels, tick, line, pos, outer, font, lty, lwd, lwd.ticks, col, col.ticks, hadj, padj) — draw an axis where and how you want (sides 1–4 as usual).box(which="plot", lty="solid") — frame the "plot", "figure", "inner", or "outer" region.trans3d(x, y, z, pmat) — project 3-D points onto a persp plot, using the perspective matrix that persp returns. The bridge between 3-D surfaces and 2-D annotation.Copyright. These slides are adapted from R in a Nutshell: A Desktop Quick Reference (2nd ed.) by Joseph Adler, O’Reilly Media. All rights reserved by the original author and publisher.
Non-commercial use only. These materials are strictly for educational purposes and may not be used for commercial gain.
Attribution. Any reproduction, distribution, or use of these materials must properly credit the original source.
R in a Nutshell: A Desktop Quick Reference