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, -- Jonas Stein <news at jonasstein.de>
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 kind regards, -- Jonas Stein <news at jonasstein.de>
Hello, You can use your function with 'lapply' getSIstring(2e7) getSIstring(2e-8) lapply(c(2e7, 2e-8, 1234), getSIstring) # as a list unlist(lapply(c(2e7, 2e-8, 1234), getSIstring)) # as a character vector or you can include the 'lapply' in the function body getSIstring2 <- function(x){ f <- function(x){ 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 } sistring } prefixpairs <- data.frame(factor=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), prefix=c("Y", "Z", "E", "P", "T", "G", "M", "k", " ", "m", "u", "n", "p", "f", "a", "z", "y")) x <- sort(x) # needed? unlist(lapply(x, f)) } getSIstring2(2e7) getSIstring2(2e-8) getSIstring2(c(2e7, 2e-8)) getSIstring2(c(2e7, 2e-8, 1234)) I've included the value 1234 because I coudn't understand wether it could be passed to the function. To return '1 k', use a 'round' inside the paste to round the division value. See ?round Rui Barradas -- View this message in context: http://r.789695.n4.nabble.com/automatic-SI-prefixes-as-ticklabels-on-axis-tp4266141p4267911.html Sent from the R help mailing list archive at Nabble.com.
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
Ben's solution is much better, I was using only Jonas' code. There might be "typo" with large values of 'x',> getSIstring(1e309)[1] "Inf Y" I don't believe this will happen, the range upper limit is much smaller. Anyway, it can be easily solved. (Ben's code, slightly changed.) 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) ifelse(length(ix) > 0, sistring <- paste(x/lut[ix], pre[ix]), sistring <- as.character(x)) sistring[which(sistring == "Inf Y")] <- "Inf" # make it look better return(sistring) } getSIstring(c(4.2e-3, 2e7)) x1 <- .Machine$double.xmax x2 <- x1 + 10^(308 - 16) getSIstring(c(x1, x2)) Rui Barradas -- View this message in context: http://r.789695.n4.nabble.com/automatic-SI-prefixes-as-ticklabels-on-axis-tp4266141p4269182.html Sent from the R help mailing list archive at Nabble.com.