# 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. May 24, 2013 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, 2013 at 13:42
• @whuber Effectively, were you replacing the axes by a sort of rug plot? Feb 24, 2015 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, 2015 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. Feb 24, 2015 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/

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)


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)

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"