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]]