163

I'm using R and ggplot to draw a scatterplot of some data, all is fine except that the numbers on the y-axis are coming out with computer style exponent formatting, i.e. 4e+05, 5e+05, etc. This is unacceptable to me, so I want to get it to display them as 500,000, 400,000, and so on. Getting a proper exponent notation would also be acceptable.

The code for the plot is as follows:

p <- ggplot(valids, aes(x=Test, y=Values)) +
  geom_point(position="jitter") +
  facet_grid(. ~ Facet) +
  scale_y_continuous(name="Fluorescent intensity/arbitrary units") +
  scale_x_discrete(name="Test repeat") +
  stat_summary(fun.ymin=median, fun.ymax=median, fun.y=median, geom="crossbar")

Any help much appreciated.

Jack Aidley
  • 19,439
  • 7
  • 43
  • 70
  • 40
    Be careful of describing `ggplot` default options as "obviously unacceptable". You mean you have a *personal preference* for a different format. A number in the format `4e+05` is scientific notation, and would be the preferred formatting in a wide variety of applications. – Andrie Jul 23 '12 at 10:13

5 Answers5

167

Another option is to format your axis tick labels with commas is by using the package scales, and add

 scale_y_continuous(name="Fluorescent intensity/arbitrary units", labels = comma)

to your ggplot statement.

If you don't want to load the package, use:

scale_y_continuous(name="Fluorescent intensity/arbitrary units", labels = scales::comma)
Axeman
  • 32,068
  • 8
  • 81
  • 94
83

I also found another way of doing this that gives proper 'x10(superscript)5' notation on the axes. I'm posting it here in the hope it might be useful to some. I got the code from here so I claim no credit for it, that rightly goes to Brian Diggs.

fancy_scientific <- function(l) {
     # turn in to character string in scientific notation
     l <- format(l, scientific = TRUE)
     # quote the part before the exponent to keep all the digits
     l <- gsub("^(.*)e", "'\\1'e", l)
     # turn the 'e+' into plotmath format
     l <- gsub("e", "%*%10^", l)
     # return this as an expression
     parse(text=l)
}

Which you can then use as

ggplot(data=df, aes(x=x, y=y)) +
   geom_point() +
   scale_y_continuous(labels=fancy_scientific) 
Jack Aidley
  • 19,439
  • 7
  • 43
  • 70
  • 11
    If you don't want 0 to be printed as "0 x 10⁺⁰", add the following below the `format(...)` line: `l <- gsub("0e\\+00","0",l)` – semi-extrinsic Sep 15 '15 at 10:12
  • 1
    If you want to special case other things, it's easiest to add more `gsub()` directly after the `format()`, while testing what `format()` returns for your case in a separate console. – semi-extrinsic Sep 15 '15 at 10:15
  • 5
    add this before last `gsub` command: `# remove + after exponent, if exists. E.g.: (3x10^+2 -> 3x10^2)` `l <- gsub("e\\+","e",l)` and after it: `# convert 1x10^ or 1.000x10^ -> 10^` `l <- gsub("\\'1[\\.0]*\\'\\%\\*\\%", "", l)` to make it in format usually used in papers. – John_West Feb 23 '16 at 14:08
  • Asked a followup question to this answer here: https://stackoverflow.com/questions/63477686/how-do-i-make-ggplot2-custom-text-formats-from-axis-scale-functions-follow-forma – Jordan Mandel Aug 19 '20 at 00:26
47
x <- rnorm(10) * 100000
y <- seq(0, 1, length = 10)
p <- qplot(x, y)
library(scales)
p + scale_x_continuous(labels = comma)
DiscreteCircle
  • 684
  • 5
  • 7
  • When I try this I get an error that formatter is an unused argument? Does it need another package or something? – Jack Aidley Jul 23 '12 at 12:12
  • 4
    I changed the code to include `library(scales)` and use `comma` which should work better than the function that I had before. – DiscreteCircle Jul 23 '12 at 12:21
18

I'm late to the game here but in-case others want an easy solution, I created a set of functions which can be called like:

 ggplot + scale_x_continuous(labels = human_gbp)

which give you human readable numbers for x or y axes (or any number in general really).

You can find the functions here: Github Repo Just copy the functions in to your script so you can call them.

Feargal Ryan
  • 454
  • 3
  • 9
12

I find Jack Aidley's suggested answer a useful one.

I wanted to throw out another option. Suppose you have a series with many small numbers, and you want to ensure the axis labels write out the full decimal point (e.g. 5e-05 -> 0.0005), then:

NotFancy <- function(l) {
 l <- format(l, scientific = FALSE)
 parse(text=l)
}

ggplot(data = data.frame(x = 1:100, 
                         y = seq(from=0.00005,to = 0.0000000000001,length.out=100) + runif(n=100,-0.0000005,0.0000005)), 
       aes(x=x, y=y)) +
     geom_point() +
     scale_y_continuous(labels=NotFancy) 
EconomiCurtis
  • 2,107
  • 4
  • 23
  • 33
  • 35
    This can be shortened by using an anonymous function: `scale_y_continuous(labels=function(n){format(n, scientific = FALSE)})` Why there is no pre-defined formatter like that, hell knows. – eMPee584 Apr 23 '15 at 20:21
  • 3
    @eMPee584 Sorry for bumping this old reply but please consider making this an answer, so it can be found more easily :) Your comment has more upvotes than some of the actual answers. – ByteHamster Aug 27 '20 at 07:29