Frederik Vanrenterghem wrote on 12/13/2011 01:55:03 PM:

> Hi,
> 
> Being a novice to R, I would like to create a graph in R with 2 axes.
> One of the 2 only has positive values, the other one also has negative
> values. The part I'm struggling with is how to align the 2.
> 
> Rather than starting to plot the data from the x axis, I would like to
> start plotting the positive values on the right axis only as of the 0
> value on the left axis.
> 
> Using a simple example found online, I understand how to get 2 axis on
> a single drawing, but I'm unsure how to accomplish the alignment
> objective. In the example, the 0 value of the right axis should align
> with the 0 of the left axis, and the red line should start in the
> middle of the graph only, rather than at the bottom of it.
> 
> (This is an arbitrary example - the right axis could also start as of
> value 1000, in which case I'd like 1000 to align with 0 of the left
> axis.)
> 
> Code:
> 
> # set up some fake test data
> time <- seq(0,72,12)
> betagal.abs <- c(0.05,-0.18,0.25,0.31,0.32,0.34,0.35)
> cell.density <- c(0,1000,2000,3000,4000,5000,6000)
> 
> #add extra space to right margin of plot within frame
> par(mar=c(5, 4, 4, 4) + 0.1)
> 
> # Plot first set of data and draw its axis
> plot(time, betagal.abs, pch=16, axes=F, ylim=c(-1,1), xlab="",
> ylab="", type="b",col="black", main="Mike's test data")
> axis(2, ylim=c(-1,1),col="black")
> mtext("Beta Gal Absorbance",side=2,line=2.5)
> box()
> 
> # Allow a second plot on the same graph
> par(new=T)
> 
> # Plot the second plot and put axis scale on right
> plot(time, cell.density, pch=15,  xlab="", ylab="", ylim=c(0,7000),
> axes=F, type="b", col="red")
> mtext("Cell Density",side=4,col="red",line=2.5)
> axis(4, ylim=c(0,7000), col="red",col.axis="red")
> 
> # Draw the time axis
> axis(1,pretty(range(time),10))
> mtext("Time (Hours)",side=1,col="black",line=2.5)
> 
> # Add Legend
> legend(5,7000,legend=c("Beta Gal","Cell
> Density"),text.col=c("black","red"),pch=c(16,15),col=c("black","red"))
> 
> Thanks in advance for any help you can provide!
> 
> Best regards,
> Frederik Vanrenterghem


Use a function to convert units between the two y axes, then, rather than 
adding a second plot to the graph, just add another line using the same 
coordinates that you set up originally.

For example:


# this function converts units between the two y axes
# the inputs are two points on the y1 axis (y1a and y1b) 
#       which should line up with two points on the y2 axis (y2a and y2b)
# use to=1 to convert from y2 to y1 units, 
#       use to=2 to convert from y1 to y2 units
convert.y <- function(y1a, y1b, y2a, y2b, y, to=1) {
        slope <- (y1b - y1a) / (y2b - y2a)
        intercept <- y1a - slope * y2a
        if(to==1) intercept + slope * y else (y - intercept) / slope
        }

# set up some fake test data 
time <- seq(0, 72, 12) 
betagal.abs <- c(0.05, -0.18, 0.25, 0.31, 0.32, 0.34, 0.35) 
cell.density <- (0:6)*1000

# plot the first line
par(mar=c(5, 4, 4, 4) + 0.1) 
plot(time, betagal.abs, pch=16, axes=F, ylim=c(-1,1), type="b" 
        xlab="Time (Hours)", ylab="Beta Gal Absorbance", 
        main="Mike's test data") 
mtext("Cell Density", side=4, col="red", line=2.5) 

# add the second line
dens.conv <- convert.y(y1a=0, y1b=1, y2a=min(cell.density), 
        y2b=max(cell.density), cell.density, 1)
points(time, dens.conv, pch=15,  type="b", col="red") 

# add axes
axis(1) 
axis(2) 
box() 
tick.labels <- pretty(cell.density)
tick.locations <- convert.y(y1a=0, y1b=1, y2a=min(cell.density), 
        y2b=max(cell.density), tick.labels, 1)
axis(4, at=tick.locations, labels=tick.labels, col="red", col.axis="red") 

# add legend
legend("topleft", legend=c("Beta Gal", "Cell Density"), 
        text.col=c("black","red"), pch=c(16,15), col=c("black", "red")) 


Jean
	[[alternative HTML version deleted]]

