From ripley at stats.ox.ac.uk  Sun May  1 06:40:51 2005
From: ripley at stats.ox.ac.uk (Prof Brian Ripley)
Date: Sun May  1 06:41:04 2005
Subject: [Rd] RE: as.numeric method for objects of class "difftime"
In-Reply-To: <B998A44C8986644EA8029CFE6396A9241B32D6@exqld2-bne.qld.csiro.au>
References: <B998A44C8986644EA8029CFE6396A9241B32D6@exqld2-bne.qld.csiro.au>
Message-ID: <Pine.LNX.4.61.0505010537230.19647@gannet.stats>

I am very surprised that people would expect as.numeric to do something 
meaningful on time differences (or times, come to that).  Perhaps the best 
thing is to stop it altogether.

The selection of "auto" was the best for the original purpose: people in 
general do not want a difference of 3 days expressed in seconds.  The 
problems only arise if the result is unclassed, and I still do not 
understand why that is a reasonable thing to do.

On Sun, 1 May 2005 Bill.Venables@csiro.au wrote:

> I had a couple of private replies to the message below, all very
> supportive of the idea.  I see that where I should have looked first is
> at the function difftime, the constructor (which will hardly ever be
> used except by people who know about its separate existence from
> Ops.POSIXt).
>
> Thus encouraged I formally propose that a method for as.numeric be
> provided that will not break existing code, but will issue a warning if
> people convert from difftime to numeric without specifying a time unit
> to which the resulting numerical quantity will implicitly refer.
>
> This is the simplest acceptable solution I could think of.  The code I
> propose is as follows:
>
> ###
> ### S3 method for objects of class 'difftime'
> ###
> as.double.difftime <- function(x, units = attr(x, "units"), ...) {
>  if(missing(units)) {
>    warning('No time units specified for conversion to numeric.\n"',
>             units, '" has been assumed.')
>    return(as.vector(x))
>  }
>  cfToSecs <- cumprod(c(secs = 1, mins = 60, hours = 60, days = 24,
> weeks = 7))
>  if(!is.element(units, names(cfToSecs)))
>    stop("Unknown time units. Acceptable time units are\n\t",
>         paste('"', names(cfToSecs), '", ', sep = "", collapse = ""),
>         "only.")
>  as.vector(x) * (cfToSecs[attr(x, "units")]/cfToSecs[units])
> }
> ###
> ### End S3 method
> ###
>
> Note that if people want to continue business as usual and the warning
> irritates them, the simplest solution is to use as.vector instead of
> as.numeric.  I think this is reasonable: to me as.vector implies simply
> a change of structure to the object, whereas as.numeric implies a
> conversion to a reasonably intuitive numerical object corresponding to
> the original.
>
> In retrospect the best thing to have done would have been not to make
> "auto" the default units for difftime, but "secs" instead, but I think
> that particular horse has bolted by now.
>
> I would welcome further discussion.
>
> Bill.
>
> : -----Original Message-----
> : From: Venables, Bill (CMIS, Cleveland)
> : Sent: Saturday, 30 April 2005 4:03 PM
> : To: 'R-Devel (r-devel@stat.math.ethz.ch)'
> : Subject: as.numeric method for objects of class "difftime"
> :
> :
> : I have just become painfully aware that objects of class
> : "difftime", generated by the difference of two POSIXct
> : objects, carry a "units" attribute, which flashes by when the
> : object is printed, for example.
> :
> : The pain was occasioned when I tried to turn these objects
> : into numberic objects for use elsewhere as a covariate.
> :
> : as.numeric(difftime object)
> :
> : simply turns off the units attribute and provides a numeric
> : object which may represent a number of seconds or a number of
> : days, with no warning as to which.
> :
> : I think this is an unfortunate situation, but I can't see how
> : to rectify it without breaking code that may rely on this
> : quirky feature.  My inclination is to suggest a method for
> : as.numeric (ie for as.double) that settles on a single unit,
> : which for consistency with as.numeric(POSIXct object) should
> : probably be seconds:
> :
> : as.double.difftime <- function(x, ...)
> :   if(attr(x, "units") == "days") as.vector(x) * 86400 else
> : as.vector(x)
> :
> : but there must now be lots of code out there that has
> : blythely assumed that the difference will always be a number
> : of days and others assume it is always seconds.
> :
> : At the very least I think the help information should carry a
> : big red warning about this rather unusual feature.  (It may,
> : I suppose, but I couldn't find it.)
> :
> : Comments?
> :
> : Bill Venables,
> : CMIS, CSIRO Laboratories,
> : PO Box 120, Cleveland, Qld. 4163
> : AUSTRALIA
> : Phone:  +61 7 3826 7251
> : Fax:    +61 7 3826 7304
> : Mobile: +61 4 1963 4642
> : Home:   +61 7 3286 7700
> : mailto:Bill.Venables@csiro.au
> : http://www.cmis.csiro.au/bill.venables/
> :
> :
>
> ______________________________________________
> R-devel@stat.math.ethz.ch mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>

-- 
Brian D. Ripley,                  ripley@stats.ox.ac.uk
Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272866 (PA)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595


[Rd] RE: as.numeric method for objects of class "difftime"
Prof Brian Ripley