ggplot2 y axis label decimal precision

Go To StackoverFlow.com

18

I am plotting several ggplot charts in a loop (i know, i know don't loop use plyr...but) and was curious if there was a way to set the decimal precision to say one decimal (i.e. 0.0). I am using the following scale transformation.

p <- p + scale_y_log10()

Any help would be appreciated.

2012-04-05 20:48
by MikeTP


22

I was kind of under the impression that one decimal (i.e 1.2) was the default, but if you're seeing more decimal places than that, you can pass your own formatting to the scale:

fmt_dcimals <- function(decimals=0){
   # return a function responpsible for formatting the 
   # axis labels with a given number of decimals 
   function(x) as.character(round(x,decimals))
}

And then add the scale to your plot:

ggplot( ... ) + scale_y_log10(labels = fmt_dcimals(2))

Now that I think about this, I should add that if you're really going to write your own formatter, you should probably stick to using the format function to do the work, rather than rounding and coercing. That's probably safer and "nicer".

As an example, to force two digits after the decimal, you could change this formatting function to something like this:

fmt_dcimals <- function(decimals=0){
    function(x) format(x,nsmall = decimals,scientific = FALSE)
}

and you can further play with the nsmall and digits arguments to format to get what you want, I think. An example of it's use:

df <- data.frame(x = 1:5,y = rexp(5))
ggplot(df,aes(x = x,y=y)) + 
    geom_point() + 
    scale_y_log10(labels = fmt_dcimals(2))

enter image description here

2012-04-05 21:09
by joran
Thank you. For consistency in axis appearance I would like to always have two decimals even if the number rounds evenly to one decimal. Is there a way to make the round function always return two decimals (i.e. round (22.50,2) returns 22.5 instead of 22.50) - MikeTP 2012-04-06 13:44
@MikeTP Sorry for the delay. I think my edit addresses your question - joran 2012-04-06 18:23
why do you have a function within a function - naught101 2012-11-22 02:51
@naught101 The more recent versions of ggplot were rewritten such that the labels argument to most scale_* functions takes a function as a value. In the associated scales package you will find lots of formatting functions that actual return functions that are used to format labels. In short, wrapping it in fmt() makes our code in scale_* much more concise, compared to writing out the whole function as an argument to scale_* - joran 2012-11-22 03:49
@joran: that makes no sense to me. Why wouldn't you just to fmt<-function(x){format(x,nsmall = 2,scientific = FALSE)} ; ggplot(df,aes(x = x,y=y)) + scale_y_log10(labels = fmt)? (note missing () from scale call). It does exactly the same thing, but it passes the function directly to ggplot, instead of passing a function that passes a function - naught101 2012-11-22 04:01
@naught101 For this particular example, you're right, it's doesn't matter much. But that's just because we don't need to pass any arguments through. Consider date_format. If we do what you describe with that one, how do we pass different date formats along? Now consider an even more complicated example, like math_format. So I was just sticking with the conventional format, that's all - joran 2012-11-22 08:59
Nice use of a closure. Via the partial function from the pryr package you can get similar behavior in much shorter code: labels = partial(sprintf, fmt = '%0.2f') - Paul Hiemstra 2016-12-02 10:11
Ads