gavin.simpson@ucl.ac.uk
2005-Jun-02 13:45 UTC
[Rd] Wishlist: more flexible handling of tick labels in axis.Date (PR#7913)
Full_Name: Gavin Simpson Version: 2.1.0-patched (1-Jun-2005) OS: Linux (Fedora Core 3) Submission from: (NULL) (128.40.32.76) axis.Date() insists on labelling tick marks. It could be made more flexible by allowing the user to specify if they want the ticks to be labelled, for example, to add un-labelled minor ticks for "months", added to a plot with "years" labelled. The user can not define labels = "" in the "..." in the call to axis.Date() as axis.Date() calls axis() with labels = labels explicitly, resulting in: Error in axis(side, at = z, labels = labels, ...) : formal argument "labels" matched by multiple actual arguments if you try. One way round this would be to add labels as a named argument to axis.Date() and to allow labels to be NULL (missing), TRUE or FALSE. A first attempt at this is shown below: axis.Date2 <- function (side, x, at, format, labels, ...) { mat <- missing(at) if (!mat) x <- as.Date(at) else x <- as.Date(x) range <- par("usr")[if (side%%2) 1:2 else 3:4] range[1] <- ceiling(range[1]) range[2] <- floor(range[2]) d <- range[2] - range[1] z <- c(range, x[is.finite(x)]) class(z) <- "Date" if (d < 7) if (missing(format)) format <- "%a" if (d < 100) { z <- structure(pretty(z), class = "Date") if (missing(format)) format <- "%b %d" } else if (d < 1.1 * 365) { zz <- as.POSIXlt(z) zz$mday <- 1 zz$mon <- pretty(zz$mon) m <- length(zz$mon) m <- rep.int(zz$year[1], m) zz$year <- c(m, m + 1) z <- .Internal(POSIXlt2Date(zz)) if (missing(format)) format <- "%b" } else { zz <- as.POSIXlt(z) zz$mday <- 1 zz$mon <- 0 zz$year <- pretty(zz$year) z <- .Internal(POSIXlt2Date(zz)) if (missing(format)) format <- "%Y" } if (!mat) z <- x[is.finite(x)] z <- z[z >= range[1] & z <= range[2]] z <- sort(unique(z)) # if labels is missing or TRUE generate labels for ticks if (missing(labels) || labels == TRUE) labels <- format.Date(z, format = format) # else rep "" to suppress labelling else labels <- rep("", length(z)) axis(side, at = z, labels = labels, ...) } An example of using this with the Date example from ?plot.Date : random.dates <- as.Date("2001/1/1") + 70*sort(runif(100)) plot(random.dates, 1:100, xaxt="n") axis.Date2(1, at=seq(as.Date("2001/1/1"), max(random.dates)+6, "weeks")) axis.Date2(1, at=seq(as.Date("2001/1/1"), max(random.dates)+6, "days"), labels = FALSE, tcl = -0.2) The function should perhaps enforce NULL/TRUE/FALSE for labels, or could be enhanced to allow labels = "" explicitly or to allow user defined vector for labels that is of length(at). Thanks, Gavin
Duncan Murdoch
2005-Jun-02 14:48 UTC
[Rd] Wishlist: more flexible handling of tick labels in axis.Date (PR#7913)
I think allowing the user to change the labels is a good idea, but have some nitpicking about the details. - Could you grab a copy of the current axis.Date source from https://svn.r-project.org/R/trunk/src/library/graphics/R/datetime.R and edit that, rather than what you see in R? There are some comments in the source that shouldn't be lost. This will also mean that it's easier to detect what changes you've made. - I'd prefer the interpretation of the labels argument to be very similar to what axis() does, i.e. NULL should not be treated specially. (Actually, I think axis() treats labels=NULL as TRUE, but that's undocumented and might be an accident.) - axis.POSIXct() should be modified in a corresponding way. - Your test if (missing(labels) || labels == TRUE) will generate warnings if a vector of labels is passed in. A better test is "identical(labels, TRUE)". - If you set the default value for labels to TRUE, then you don't need the "missing(labels)" part of the test. - Could you also edit https://svn.r-project.org/R/trunk/src/library/graphics/man/axis.POSIXct.Rd to reflect your changes? If you want help with this feel free to contact me off the list; when you're done, you can send me the files and I'll review and commit the changes. Duncan Murdoch gavin.simpson@ucl.ac.uk wrote:> Full_Name: Gavin Simpson > Version: 2.1.0-patched (1-Jun-2005) > OS: Linux (Fedora Core 3) > Submission from: (NULL) (128.40.32.76) > > > axis.Date() insists on labelling tick marks. It could be made more flexible by > allowing the user to specify if they want the ticks to be labelled, for example, > to add un-labelled minor ticks for "months", added to a plot with "years" > labelled. The user can not define labels = "" in the "..." in the call to > axis.Date() as axis.Date() calls axis() with labels = labels explicitly, > resulting in: > > Error in axis(side, at = z, labels = labels, ...) : > formal argument "labels" matched by multiple actual arguments > > if you try. > > One way round this would be to add labels as a named argument to axis.Date() and > to allow labels to be NULL (missing), TRUE or FALSE. A first attempt at this is > shown below: > > axis.Date2 <- function (side, x, at, format, labels, ...) > { > mat <- missing(at) > if (!mat) > x <- as.Date(at) > else x <- as.Date(x) > range <- par("usr")[if (side%%2) > 1:2 > else 3:4] > range[1] <- ceiling(range[1]) > range[2] <- floor(range[2]) > d <- range[2] - range[1] > z <- c(range, x[is.finite(x)]) > class(z) <- "Date" > if (d < 7) > if (missing(format)) > format <- "%a" > if (d < 100) { > z <- structure(pretty(z), class = "Date") > if (missing(format)) > format <- "%b %d" > } > else if (d < 1.1 * 365) { > zz <- as.POSIXlt(z) > zz$mday <- 1 > zz$mon <- pretty(zz$mon) > m <- length(zz$mon) > m <- rep.int(zz$year[1], m) > zz$year <- c(m, m + 1) > z <- .Internal(POSIXlt2Date(zz)) > if (missing(format)) > format <- "%b" > } > else { > zz <- as.POSIXlt(z) > zz$mday <- 1 > zz$mon <- 0 > zz$year <- pretty(zz$year) > z <- .Internal(POSIXlt2Date(zz)) > if (missing(format)) > format <- "%Y" > } > if (!mat) > z <- x[is.finite(x)] > z <- z[z >= range[1] & z <= range[2]] > z <- sort(unique(z)) > # if labels is missing or TRUE generate labels for ticks > if (missing(labels) || labels == TRUE) > labels <- format.Date(z, format = format) > # else rep "" to suppress labelling > else labels <- rep("", length(z)) > axis(side, at = z, labels = labels, ...) > } > > An example of using this with the Date example from ?plot.Date : > > random.dates <- as.Date("2001/1/1") + 70*sort(runif(100)) > plot(random.dates, 1:100, xaxt="n") > axis.Date2(1, at=seq(as.Date("2001/1/1"), max(random.dates)+6, "weeks")) > axis.Date2(1, at=seq(as.Date("2001/1/1"), max(random.dates)+6, "days"), > labels = FALSE, tcl = -0.2) > > The function should perhaps enforce NULL/TRUE/FALSE for labels, or could be > enhanced to allow labels = "" explicitly or to allow user defined vector for > labels that is of length(at). > > Thanks, > > Gavin > > ______________________________________________ > R-devel@stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel