djq
djq

Reputation: 15298

How can I make the following plot using R?

I would like to make a plot with 4 axes in R so that it looks similar to this plot:

enter image description here

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: enter image description here

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

Answers (1)

joran
joran

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

Related Questions