Reputation: 2413
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?
Upvotes: 12
Views: 2772
Reputation: 24069
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.
Upvotes: 13