Search code examples
rplotaxispar

Aligning or scaling two y axes: Zero values of y1 & y2 should be exactly opposite in R


Load sample data and plot:

x <- 1:5
y1 <- rnorm(5)
y2 <- rnorm(5,20)
par(mar=c(5,4,4,5)+.1)
plot(x,y1,type="l",col="red")
par(new=TRUE)
plot(x, y2,,type="l",col="blue",xaxt="n",yaxt="n",xlab="",ylab="")
axis(4)
mtext("y2",side=4,line=3)
legend("topleft",col=c("red","blue"),lty=1,legend=c("y1","y2"))`

Above code will you this picture

enter image description here

What am I stuck at?

I want to align the two y-axes such that zero values on y1 and y2 to be opposite to each-other.

Any help?

Please let me know if you have any questions or clarification. Thanks!


Solution

  • Below listed code should work for aligning two-y-axes to baseline; however, y1 has strange values rather than 0 (in some plots #remember I am plotting 80 two-y-axes plots), this will require adjustment in my algorithm for setting y-axes range, but otherwise plot(s) seem ok. Let me know if you find out the reason or have any clarification(s).

    rangeY1=range(df$y1, na.rm=TRUE, finite=TRUE)
    
    rangeY2=range(df$y2, na.rm=TRUE, finite=TRUE)
    
    # Scales of the given ranges
    sumY1= rangeY1[2]-rangeY1[1]
    sumY2= rangeY2[2]-rangeY2[1]
    # Relative part of the positive and negative axis, only temporary variables
    R=abs(rangeY1[1]/sumY1)
    S=abs(rangeY2[1]/sumY2)
    K=abs(rangeY1[2]/sumY1)
    L=abs(rangeY2[2]/sumY2)
    #Select new minimum values for the ranges
    if(R>S){
      new_miny1=rangeY1[1]
      new_miny2=sumY2*rangeY1[1]/sumY1 }
    if(S>R){
      new_miny1=sumY1*rangeY2[1]/sumY2
      new_miny2=rangeY2[1] }
    if(S==R){
      new_miny1=rangeY1[1]
      new_miny2=rangeY2[1] }
    #Select new maximum values for the ranges
    if(K>L){
      new_maxy1=rangeY1[2]
      new_maxy2=sumY2*rangeY1[2]/sumY1 }
    if(L>K){
      new_maxy1=sumY1*rangeY2[2]/sumY2
      new_maxy2=rangeY2[2] }
    if(K==L){
      new_maxy1=rangeY1[2]
      new_maxy2=rangeY2[2] }
    #"New ranges"
    new_rangeY1=c(new_miny1, new_maxy1)
    new_rangeY2=c(new_miny2, new_maxy2)