Producing plots where axis are to same scale

#1
Hello,


I'm trying to produce a plot of topography, and I want distance (x) to be plotted to the same scale as elevation (y), so that n units on the x axis equal the same length as n units on the y axis.

I've had a go as below:

plot(Point,CElev,
asp=1,
type="l"
)

This works, but what I also want to do is reduce the size of the y-axis so that the chart is only as tall as it needs to be.

I have tried the following:

plot(Point,CElev,
asp=1,
type="l",
xlim=range(Point),
ylim=range(CElev)
)

Unfortunately this does not seem to work, as it looks as though the plot area can't be changed, so my plots are always 'streched' to fill the available window.

I could specify window size perhaps, but I want to be able to use this script to automatically plot charts from lots of data sets, so for each graph the range of CElev would be different, therefore I can't specify the chart dimensions before hand.

Thanks for taking a look.
 

Mike White

TS Contributor
#2
This problem has appeared several times on the R-project website. The simplest solution is to use xyplot in the lattice library, e.g.
Code:
dat<-data.frame(Point=seq(0,1000,by=100), CElev=c(0,25,50,100,120,90,70,80,90,95,100))
library(lattice)
attach(dat)
xyplot(CElev ~ Point, ylim = range(CElev), type="l", aspect = "iso")
detach(dat)
Greg Snow has also produced a squishplot function that does the same job:
Code:
# function written by Greg Snow
squishplot <- function(xlim,ylim,asp=1){
   if(length(xlim) < 2) stop('xlim must be a vector of length 2')
   if(length(ylim) < 2) stop('ylim must be a vector of length 2')

  tmp <- par(c('plt','pin','xaxs','yaxs'))

  if( tmp$xaxs == 'i' ){ # not extended axis range

        xlim <- range(xlim)
  } else { # extended range

	tmp.r <- diff(range(xlim))
	xlim <- range(xlim) + c(-1,1)*0.04*tmp.r

  }

  if( tmp$yaxs == 'i' ){ # not extended axis range

        ylim <- range(ylim)
  } else { # extended range

	tmp.r <- diff(range(ylim))
	ylim <- range(ylim) + c(-1,1)*0.04*tmp.r

  }

  tmp2 <- (ylim[2]-ylim[1])/(xlim[2]-xlim[1])

  tmp.y <- tmp$pin[1] * tmp2 * asp

  if(tmp.y < tmp$pin[2]){ # squish vertically
	par(pin=c(tmp$pin[1], tmp.y))
	par(plt=c(tmp$plt[1:2], par('plt')[3:4]))
  } else { # squish horizontally
	tmp.x <- tmp$pin[2]/tmp2/asp
	par(pin=c(tmp.x, tmp$pin[2]))
	par(plt=c(par('plt')[1:2], tmp$plt[3:4]))

  }

  return(invisible(tmp['plt']))
} # end of function
###################

# example of using squishplot
attach(dat)
# set up plot and save original plot parameters as tmp
tmp<-squishplot(xlim=range(Point), ylim=range(CElev), asp=1)
plot(Point, CElev, type="l", las=1, cex.axis=0.8)
# reset plot parameters
detach(dat)

par(tmp)