[R] automatic SI prefixes as ticklabels on axis

Ben Tupper btupper at bigelow.org
Fri Jan 6 04:30:12 CET 2012


On Jan 5, 2012, at 8:02 PM, Jonas Stein wrote:

> On 2012-01-05, Jonas Stein <news at jonasstein.de> wrote:
>> i want to plot values with frequency on a logarithmic x axis.
>> similar to this example that i found in the web:
>> http://www.usspeaker.com/jensen%20p15n-graph.gif
>> 
>> I would like to convert long numbers to si prefix notation 
>> like in the example
>> 
>> (200000 to 200k, 35000000 to 3.5 M)
>> 
>> Of course i could create labels by hand, but
>> i have many files so i need some automatic function.
>> 
>> Has anyone done that in R?
>> 
>> Kind regards and thank you for your help,
> 
> my first try looks like this:
> ==================================
> 
> getSIstring <- function(x){
> 
>  sistring <- paste(x);
> 
>  prefixpairs <- data.frame(c(1e24,1e21,1e18,1e15,1e12,1e9,1e6,1e3,1e0,
>                              1e-3,1e-6,1e-9,1e-12,1e-15,1e-18,1e-21,1e-24),
>                            c("Y", "Z", "E", "P", "T", "G", "M", "k", " ",
>                              "m", "u", "n", "p", "f", "a", "z", "y"))
> 
>  colnames(prefixpairs) <- c("factor", "prefix")
>  i=0
>  repeat{i=i+1;
>         if (x > prefixpairs$factor[i]) {
>           sistring <- paste(x/prefixpairs$factor[i], prefixpairs$prefix[i]); break;}
>         if (i >= length(prefixpairs$factor)) break}
> 
>   return(sistring)
> }
> 
> ==================================
> 
>> getSIstring(2e7)
> [1] "20 M"
> 
> How can i improve this function?
> It would be nice if it could handle lists too like sin() can do
>> sin(1:4)
> [1]  0.8414710  0.9092974  0.1411200 -0.7568025
> 

How about using findInterval - that will give you the behavior you describe.  Note I had to reverse the order of your table and I did not make it a data frame.

getSIstring <- function(x){

lut <- rev(c(1e24,1e21,1e18,1e15,1e12,1e9,1e6,1e3,1e0,
                             1e-3,1e-6,1e-9,1e-12,1e-15,1e-18,1e-21,1e-24))
pre <- rev(c("Y", "Z", "E", "P", "T", "G", "M", "k", " ",
                             "m", "u", "n", "p", "f", "a", "z", "y"))

 ix <- findInterval(x, lut)
 
  if (length(ix) > 0 ) {
    sistring <- paste(x/lut[ix], pre[ix])
  } else {
    sistring <- as.character(x)
  }

  return(sistring)
}


> getSIstring(c(4.2e-3,2e7))
[1] "4.2 m" "20 M" 


Cheers,
Ben





> kind regards,
> 
> -- 
> Jonas Stein <news at jonasstein.de>
> 
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

Ben Tupper
Bigelow Laboratory for Ocean Sciences
180 McKown Point Rd. P.O. Box 475
West Boothbay Harbor, Maine   04575-0475 
http://www.bigelow.org



More information about the R-help mailing list