Question

I want the y-axis to be scaled:

  1. by log10, I used:

    scale_y_log10(breaks = trans_breaks("log10",function(x) 10^x))

  2. more ticks:

    scale_y_continuous(breaks=pretty_breaks(10))

But from the error message, there can by only one scale. Is there a way to have both of the two scales?

Was it helpful?

Solution

if I understand your question right, you want to have a y axis on a log scale with more ticks than just 1, 10, 100, etc. Here's a reproducible example describing what you tried:

library(ggplot2)
library(scales)
dat <- data.frame(X=1:3, Y=c(2,50,10000))
ggplot(data=dat, aes(x=X, y=Y)) + geom_point() + 
  scale_y_log10(breaks=trans_breaks("log10",function(x) 10^x)) +
  scale_y_continuous(breaks=pretty_breaks(10))

## Error: Scale for 'y' is already present. Adding another scale for 'y', which will replace the existing scale.

OK, this error says we're only allowed one call to scale_y_something. Since you want log scale, let's keep scale_y_log10. Our approach from here depends on what you want to achieve - would it work to simply have more evenly spaced ticks along your axis, even if they aren't nice round numbers? If so, you can let pretty() add additional breaks by choosing a higher-than-normal value for n (which ?trans_breaks promises will be passed to pretty):

ggplot(data=dat, aes(x=X, y=Y)) + geom_point() + 
  scale_y_log10(breaks=trans_breaks("log10", function(x) 10^x, n=20))

Flexible, maybe, but ugly. You can explore what trans_breaks is doing by applying the result to your data (dat$Y in this example). Note that the value of n is taken as a suggestion rather than a command:

trans_breaks("log10", function(x) 10^x, n=2 )(dat$Y)
[1]     1   100 10000

trans_breaks("log10", function(x) 10^x, n=10)(dat$Y)
[1]     1.000     3.162    10.000    31.623   100.000   316.228  1000.000  3162.278 10000.000

Or maybe you'd prefer ticks of the form 1, 3, 10, 30, 100, etc.? If so:

ggplot(data=dat, aes(x=X, y=Y)) + geom_point() + 
  scale_y_log10(breaks=c(1,3,10,30,100,300,1000,3000,10000))

My guess is these direct specifications are your best bet. But if you also need flexibility for an arbitrary y range, take a hint from https://stackoverflow.com/a/14258838/3203184 and add a labels argument:

ggplot(data=dat, aes(x=X, y=Y)) + geom_point() + 
  scale_y_log10(breaks=trans_breaks("log10", function(x) 10^x, n=20), 
                labels=trans_format("log10", math_format(10^.x)))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top