# Removing borders in R plots for achieving Tufte's axis

Consider the following graph:

x <- 1:100
y1 <- rnorm(100)
y2 <- rnorm(100)+100

par(mar=c(5,5,5,5))

plot(x,y1,pch=0,type="b",col="red",yaxt="n",ylim=c(-8,2),ylab="")
axis(side=2, at=c(-2,0,2))
mtext("red line", side = 2, line=2.5, at=0)

par(new=T)
plot(x,y2,pch=1,type="b",col="blue",yaxt="n",ylim=c(98,108), ylab="")
axis(side=4, at=c(98,100,102), labels=c("98%","100%","102%"))
mtext("blue line", side=4, line=2.5, at=100)


How can I remove the automatically generated borders and preserve just the axis lines, to achieve a Tufte's style?

-
Look at the bty argument in ?par, for example, bty="n". You can pass this argument in your call to plot. – Glen_b May 24 '13 at 1:43
FWIW, Tufte went further: he showed how in some cases erasing parts of the axes themselves provides additional information, effectively turning each axis into a visual display of the range of data. Inspired by this, in 1989 I wrote software to produce small multiple plots that incorporated this design (among many others inspired by Tufte and Bill Cleveland's group) and subsequently generated several million such graphics. When you have to mine so much data visually, such principles really work. – whuber May 24 '13 at 13:42
@whuber Effectively, were you replacing the axes by a sort of rug plot? – Silverfish Feb 24 '15 at 17:08
@Silver Drawing a rug plot is a separate issue--and I also did that, too. However, even in the absence of a rug plot you can choose where to stop and start drawing each axis. When you start it at the minimum and stop it at the maximum, you have achieved a visual representation of the full range of each marginal data distribution. – whuber Feb 24 '15 at 17:10
@whuber Thanks, I now understand what you were referring to - Tufte calls this a "range-frame" (and suggests not only to stop the lines there at the extrema, but also to use the final labels to indicate their values - what he calls the "range-frame with range-labels"). For later readers wanting a reference, this is from Visual Display of Quantitative Information, Chapter 7 ("Multifunctioning Graphical Elements"). As this is a highly-viewed thread, it would be nice to see an illustration added (and given the question, some R code) of what "Tufte's axis" might really mean. – Silverfish Feb 24 '15 at 17:20

Add bty="n" in both plot commands.

For time series, add frame.plot=FALSE for the same effect.

For fancier Tufte axes, see http://www.cl.cam.ac.uk/~sjm217/projects/graphics/

-
Great! Can you make it work with timeseries as a bonus? When using a zoo the border insists on appearing. – Hugo S Ferreira Nov 13 '10 at 2:12
See updated answer – Rob Hyndman Nov 13 '10 at 3:17
the "fancier" link is now dead. – Carl Jul 23 '13 at 16:37
Thanks for letting me know. I've updated the link to another site showing Tufte axes. – Rob Hyndman Jul 24 '13 at 1:24

If you use

par(bty = 'n')


Before calling plot that will fix it for zoo. It might also fix it for a variety of situations where it isn't passable to the plotting command.

(Check out bty option in the par() help for other kinds of frames for the plot)

-

This is straightforward to do, you just include the argument axes=FALSE. Consider:

x  <- 1:100
y1 <- rnorm(100)
y2 <- rnorm(100) + 100

windows()
par(mar=c(5,5,5,5))
plot(x, y1, pch=0, type="b", col="red", yaxt="n", ylim=c(-8,2), ylab="", axes=F)
axis(side=2, at=c(-2,0,2))
mtext("red line", side = 2, line=2.5, at=0)

par(new=T)
plot(x, y2, pch=1, type="b", col="blue", yaxt="n", ylim=c(98,108), ylab="", axes=F)
axis(side=4, at=c(98,100,102), labels=c("98%","100%","102%"))
mtext("blue line", side=4, line=2.5, at=100)


Note that this works equally well for histograms:

windows()
hist(y1, axes=F)


-

I am answering the more general question of removing borders in plots, without reference to Tufte.

For a histogram I did not find that btn='n' got rid of the border.

A solution that does work for histograms and should work for all types of plots is to set the line type for the border to invisible: lty="blank"

-