Reputation: 15298
I would like to make a plot with 4 axes in R so that it looks similar to this plot:
I've looked at the Quick-R website for advice and modified one of their examples (called A Silly Axis Example
):
# specify the data
x <- c(1:5); y <- x/2;
w <- c(2:4)
z <- c(1:5)
# create extra margin room on the right for an axis
par(mar=c(5, 4, 4, 8) + 0.1)
# plot x vs. y
plot(x, y,type="b", pch=21, col="red",
yaxt="n", lty=3, xlab="", ylab="")
# add x vs. 1/x
lines(x, z, type="b", pch=22, col="blue", lty=2)
# draw an axis on the left
axis(2, at=x,labels=x, col.axis="red", las=2)
# draw an axis on the right, with smaller text and ticks
axis(4, at=w,labels=round(w,digits=2),
col.axis="blue", las=2, cex.axis=0.7, tck=-.01)
# draw an axis on the top
axis(3, at=z,labels=round(z,digits=2),
col.axis="blue", las=2, cex.axis=0.7, tck=-.01)
# add a title for the right axis
mtext("L", side=3, line=3, cex.lab=1,las=2, col="blue")
# add a title for the right axis
mtext("OSR", side=4, line=3, cex.lab=1,las=2, col="red")
# add a main title and bottom and left axis labels
title("", xlab="GSI", ylab="FSI")
This code produces the following plot:
I'm having difficulty figuring out how different axes can have different scales. For example, I want the top axis L
, to go from 5 - 13, but if I set z <-c(5:13)
it will not set the axis to these values. However, I can overwrite what the labels are:
axis(3, at=z,labels=round(c(9:13),digits=2), col.axis="blue",
las=2, cex.axis=0.7, tck=-.01)
but then if I want to plot a point with these four parameters, the point will not show up in the correct place. How should I do this?
Upvotes: 2
Views: 1100
Reputation: 173697
One (perhaps cumbersome) option would be to write conversion functions that transform values between your two scales. Assuming you know the data ranges for both the top and bottom axes ahead of time, you could write a function like this:
convertScaleToBottom <- function(x,botRange,topRange){
temp <- (x - topRange[1]) / (topRange[2] - topRange[1])
return(botRange[1] + (temp * (botRange[2] - botRange[1])))
}
that takes a set of values, x
, in the top axis scale and converts them to the bottom axis scale. Then you can plot the converted values and retain the originals as the labels:
z1 <- 5:13
z1Adj <- convertScaleToBottom(z1,range(x),range(z1))
# draw an axis on the top
axis(3, at=z1Adj,labels=round(z1,digits=2),
col.axis="blue", las=2, cex.axis=0.7, tck=-.01)
This method is easily modified to reverse the order of the top axis:
convertScaleToBottomRev <- function(x,botRange,topRange){
temp <- (x - topRange[1]) / (topRange[2] - topRange[1])
return(botRange[2] - (temp * (botRange[2] - botRange[1])))
}
Upvotes: 3