12

I am trying to create a squared transform for the y-axis using scales::trans_new but am hitting an error.

MWE

data = data.frame(x = 1:10, y = runif(10), z=rnorm(10, 10)) library(ggplot2) ggplot(data, aes(x, y, size=z)) + geom_point() + scale_y_continuous(trans=scales::trans_new("sq", function(x) x^2, function(x) x^(1/2))) 

gives the error

Error in if (zero_range(as.numeric(limits))) { :
missing value where TRUE/FALSE needed

I tries adding limits and domain but got the same error.

scale_y_continuous(trans=scales::trans_new("sq", function(x) x^2, function(x) x^(1/2)), limits=c(0,1)) scale_y_continuous(trans=scales::trans_new("sq", function(x) x^2, function(x) x^(1/2), domain=c(0,1)), limits=c(0,1)) 

It seesm to be the inverse argument that is causing the error - but all values of y are positive, so I don't understand. How can I do this please?

4
  • why can't you just create a new variable for the y squared value and plot that? Commented Oct 29, 2018 at 20:10
  • 1
    @Mike ; because this takes care of axis scaling / lables -- it should be less effort ;) Commented Oct 29, 2018 at 20:13
  • 3
    last solution and then I will give up. scale_y_continuous(trans = scales::trans_new("sq", function(x){x^2}, function(x){sqrt(abs(x))})) Commented Oct 29, 2018 at 20:29
  • 1
    thanks @mike. Indeed adding abs worked. Dave2e has come to the same conclusion by the looks of it - but I thknk a slightly safer workaround. Thanks again for your help. Commented Oct 29, 2018 at 20:35

1 Answer 1

13

It seems ggplot is using the inverse function to set the y-axis limits and axis labels. If y is near zero, gglot, is padding the lower limit and is calculating a negative value. This is a "negative" (pun intended) side-effect from prettifying the limits.

Here is a work around, modifying the inverse function to prevent it from accepting a value less than zero, it will avoid the square root of a negative number error.
The lower limit of the axis will always be greater or equal to zero.

library(ggplot2) #square function sq<-function(x){ x^2 } #inverse square function (square root) isq<-function(x){ print(paste("isq",x)) #debug statement x<-ifelse(x<0, 0, x) sqrt(x) } data = data.frame(x = 1:10, y = runif(10), z=rnorm(10, 10)) print(data$y) ggplot(data, aes(x, y, size=z)) + geom_point() + scale_y_continuous(trans=scales::trans_new("sq", sq, isq)) 

Note: Remove the print function when transferring to production code.

See the link in the comment below for the bug report at Github.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.