[R] pretty for a log-axis

Martin Maechler maechler at stat.math.ethz.ch
Thu Apr 15 14:44:23 CEST 2004


>>>>> "BXC" == BXC (Bendix Carstensen) <bxc at steno.dk>
>>>>>     on Thu, 15 Apr 2004 09:54:49 +0200 writes:

    BXC> Is there a function that does the same as pretty but on
    BXC> a log-scale?  Suppose you have

    BXC> x <- exp( runif( 100, 0, 6 ) )

    BXC> (which will between 1 and 403), then I would like to
    BXC> have a result like:

    BXC> log.pretty( x )
    BXC> [1] 1 5 10 50 100 500

axTicks()  can be used for this and will use the same algorithm
that R uses internally;  it's not as flexible as pretty() is,
but should fulfill your needs.

As I (author of the function) just see, the documentation of
axTicks is insufficient:   
?axTicks points to ?par ("xaxp") which points
back to ?axTicks without explaining the crucial meaning of  axp[3]
for the log case:

axp[3]	 values
------	 ---------------
  1	   1      * 10^j
  2       (1,5)   * 10^j
  3       (1,2,5) * 10^j

Also, contrary to help(axTicks), the result of axTicks() does
not depend on the graphics state at all --- *when* all arguments
are specified (differently from the default NULL).

Here is an example "script":

## just to "repeat your example" :
> set.seed(1); x <- exp(runif(100,0,6)); rx <- range(x); summary(x)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.084   6.950  18.680  62.230  99.800 384.300 

> axTicks(1, axp=c(rx, 1), usr=c(1,3), log=TRUE)
[1]   10  100 1000
> axTicks(1, axp=c(rx, 2), usr=c(1,3), log=TRUE)
[1]   10   50  100  500 1000
> axTicks(1, axp=c(rx, 3), usr=c(1,3), log=TRUE)
[1]   10   20   50  100  200  500 1000
> axTicks(1, axp=c(rx, 3), usr=c(0,3), log=TRUE)
 [1]    1    2    5   10   20   50  100  200  500 1000

--- note that "usr" is in the log-transformed scale.

Probably the whole thing is most easily understood by looking at
the source (*including* the comments you usually won't see!)
of which the relevant part is

........
    if(log && axp[3] > 0) { ## special log-scale axp[]
        if(!any((iC <- as.integer(axp[3])) == 1:3))
            stop("invalid positive axp[3]")
        if(is.null(usr)) usr <- par("usr")[if(is.x) 1:2 else 3:4]
        else if(!is.numeric(usr) || length(usr) != 2) stop("invalid `usr'")
        ii <- round(log10(axp[1:2]))
        x10 <- 10^((ii[1] - (iC >= 2)):ii[2])
	r <- switch(iC,				## axp[3]
		    x10,			## 1
		    c(outer(c(1,  5), x10))[-1],## 2
                    c(outer(c(1,2,5), x10))[-1])## 3
        r[usr[1] <= log10(r) & log10(r) <= usr[2]]
    } else { # linear
........

Hoping that helps,
Martin Maechler




More information about the R-help mailing list