3

I'm studying the example of coord_trans() of ggplot2:

library(ggplot2)
library(scales)

set.seed(4747)    

df <- data.frame(a = abs(rnorm(26)),letters)
plot <- ggplot(df,aes(a,letters)) + geom_point()
plot + coord_trans(x = "log10")
plot + coord_trans(x = "sqrt")

I modified the code plot + coord_trans(x = "log10") as following and get what I expected:

plot + scale_x_log10(breaks=trans_breaks("log10", function(x) 10^x),
                     labels=trans_format("log10", math_format(10^.x)))

I modified the code plot + coord_trans(x = "sqrt") as following and get a strange x-axis:

plot + scale_x_sqrt(breaks=trans_breaks("sqrt", function(x) sqrt(x)),
                   labels=trans_format("sqrt", math_format(.x^0.5)))

How could I fix the problem?

tstev
  • 607
  • 1
  • 10
  • 20
ycc
  • 107
  • 8

1 Answers1

3

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: enter image description here

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: enter image description here

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: enter image description here

onlyphantom
  • 8,606
  • 4
  • 44
  • 58
  • Thank you for your help, I tried the following code: plot + scale_x_sqrt(breaks= trans_breaks("sqrt", function(x) round(sqrt(x),3), n=3)(c(0, 2)), labels=trans_format("sqrt", math_format(.x^2))) how could I get the rounded labels of ticks? I've checked the functions of scales package, not found what I could use. – ycc May 09 '18 at 03:40
  • If you want rounded numbers, then instead of round with 3, round with 0: `+ scale_x_sqrt(breaks= trans_breaks("sqrt", function(x) round(sqrt(x),0), n=5)(c(0, 5))`. `floor()` also works. Did you try that? – onlyphantom May 09 '18 at 03:43
  • I see what you meant, what if I need the expression like 12(2 is a superscript), not just 1(created by round() or floor())? – ycc May 09 '18 at 08:03
  • You would use `expression()` for that. I encourage to check out [this answer here](https://stackoverflow.com/questions/17334759/subscript-letters-in-ggplot-axis-label). If you have a more specific use-case that the answer didn't sufficiently help, then feel free to post another SO question with that use-case and I can answer there. That also help keep this answer on-topic for others who land on this question. :) – onlyphantom May 09 '18 at 10:02
  • Thank you for your help, I read the post you mentioned and the other related posts, they all discussed about the power of 10, not 2 I needed. I looked back the documentation of "math_format", and tried another way to solve my problem. This solution is not very good, but it achieved what I need. Here is my solution: options(digits=3); plot + scale_x_sqrt(breaks= trans_breaks("sqrt", function(x) round(sqrt(x),1), n=3)(c(0, 2)), labels=trans_format("sqrt", math_format(.x^2, format=signif))) – ycc May 10 '18 at 08:41