Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ggplot's sec.axis with a non-monotonic transformation

Tags:

r

ggplot2

I would like to use ggplot's sec.axis option to produce a secondary X-axis (call it Z) showing the transformation Z = X + sqrt( X^2 - X ). This transformation is not monotonic in general, but is monotonic over the range of X that is possible in my application (X > 1).

I tried the following:

x1 = seq(1, 3.5, .1)
y = rnorm( n = length(x1) )

d = data.frame( x1, y )

library(ggplot2)
ggplot( d, aes( x=x1, y=y ) ) + geom_point() +
  scale_x_continuous( sec.axis = sec_axis( ~ . + sqrt(.^2 - .) ) )

resulting in both and error and a warning:

Error in f(..., self = self) : 
  transformation for secondary axes must be monotonous
In addition: Warning message:
In sqrt(.^2 - .) : NaNs produced

Both of these suggest that it is trying to compute the transformation for values with X < 1, even though this is not necessary for the plot.

How can I plot my effectively monotonic transformation? I need a reasonably general solution since this is going in a function for which the range of X is partly user-specified (but is always > 1).

like image 424
half-pass Avatar asked Jun 16 '17 12:06

half-pass


2 Answers

Well, you could trick ggplot into believing it's monotone:

f <- Vectorize(function(x) {
  if (x < 1) return(x/1e10)
  x + sqrt(x^2 - x)
})

ggplot( d, aes( x=x1, y=y ) ) + geom_point() +
scale_x_continuous(sec.axis = sec_axis(~f(.)))

Using expand = c(0, 0) is fine but it cuts the plotting area.

like image 55
tonytonov Avatar answered Sep 27 '22 23:09

tonytonov


This problem is caused by the space before the first x value. You can remove it with expand parameter.

ggplot(d, aes(x=x1, y=y) ) + 
 geom_point() +
 scale_x_continuous(
  expand = c(0, 0),  
  sec.axis = sec_axis( ~ . + sqrt(.^2 - .) ) 
 )
like image 29
Lstat Avatar answered Sep 27 '22 23:09

Lstat