I get why you said it was a strange / terrible axis. The documentation for trans_breaks
even warns you about this in its first line:
These often do not produce very attractive breaks.
To make it less unattractive, I would use round(,2)
so my axis labels only have 2 decimal points instead of the default 8 or 9 - cluttering up the axis. Then I would set a sensible range, say in your case 0 to 5 (c(0,5)
).
Finally, you can specify the number of ticks for your axis using n
in the trans_breaks
call.
So putting it together, here's how you can format your x-axis and its tick label in the scale_x_sqrt(x)
format:
plot <- ggplot(df,aes(a,letters)) + geom_point()
plot + scale_x_sqrt(breaks=trans_breaks("sqrt", function(x) round(sqrt(x),2), n=5)(c(0, 5)))
Produces this:

The c(0,5)
is passed to pretty()
, a lesser-known Base R's function. From the documentation, pretty
does the following:
Compute a sequence of about n+1 equally spaced "round" values which cover the range of the values in x.
pretty(c(0,5))
simply produces [1] 0 1 2 3 4 5
in our case.
You can even fine-tune your axis by changing the parameters. Here the code uses 3 decimal points (round(x,3)
) and we asked for 3 number of ticks n=3
:
plot <- ggplot(df,aes(a,letters)) + geom_point()
plot + scale_x_sqrt(breaks=trans_breaks("sqrt", function(x) round(sqrt(x),3), n=3)(c(0, 5)))
Produces this:

EDIT based on OP's additional comments:
To get round integer values, floor()
or round(x,0)
works, so the following code:
plot <- ggplot(df,aes(a,letters)) + geom_point()
plot + scale_x_sqrt(breaks=trans_breaks("sqrt", function(x) round(sqrt(x),0), n=5)(c(0, 5)))
Produces this:
