tags:

views:

37

answers:

1

What if you want to apply a function other than format to a list of POSIXct objects? For instance, say I want to take a vector of times, truncate those times to the hour, and apply an arbitrary function to each one of those times.

> obs.times=as.POSIXct(c('2010-01-02 12:37:45','2010-01-02 08:45:45','2010-01-09 14:45:53'))
> obs.truncated=trunc(obs.times, units="hours")
> obs.truncated
[1] "2010-01-02 12:00:00 EST" "2010-01-02 08:00:00 EST"
[3] "2010-01-09 14:00:00 EST"

Now, I would expect the length of obs.truncated to be 3 but

> length(obs.truncated)
[1] 9

So you can see that trying to apply a function to this vector is not going to work. The class of obs.truncated is

> class(obs.truncated)
[1] "POSIXt"  "POSIXlt"

Any idea what is going on here? apply and length appear to be taking the first element of the vector as its own list.

+1  A: 

The length() of such a POSIXlt used to be reported as nine, but that got recently corrected.

Also, when I do trunc(obs.times) the wrong thing happens -- trunc() operates only once on a string of three elements. you do need apply() et al.

So here is an example of using sapply() with component-wise resetting:

> sapply(obs.times, function(.) {
+ p <- as.POSIXlt(.); 
+ p$min <- p$sec <- 0; 
+ format(p) })
[1] "2010-01-02 12:00:00" "2010-01-02 08:00:00" "2010-01-09 14:00:00"
> 

Whereas

> trunc(obs.times, units="hours")
[1] "2010-01-02 12:00:00 CST" "2010-01-02 08:00:00 CST"
[3] "2010-01-09 14:00:00 CST"
> class(trunc(obs.times, units="hours"))
[1] "POSIXt"  "POSIXlt"
> length(trunc(obs.times, units="hours"))
[1] 1
> 
Dirk Eddelbuettel
The OP includes the `class` command in the question. Also, when I call `trunc` it applies to the whole vector. But you're right: I can replicate the 9 count using R 2.10.0, but it's corrected in my R 2.11.1 console.
Shane
Oh, thanks. I removed that part.
Dirk Eddelbuettel
Great, but I'm still confused by your second paragraph. This is what I get: `base::trunc(obs.times, units="hours")` >> `[1] "2010-01-02 12:00:00 EST" "2010-01-02 08:00:00 EST" "2010-01-09 14:00:00 EST"` (same as in OP example). I also looked at the `$sec` and `$min` slots and they are all zero.
Shane
I tossed that into the main post. The length() == 1 seems fishy. R 2.11.0.
Dirk Eddelbuettel
I get `length(trunc(obs.times, units="hours"))` >> `3` in R 2.11.1 on Windoze. How odd!
Shane
Might be a bug fixed between .0 and .1 !
Dirk Eddelbuettel
Do you know if they have regression tests for things like this in base R? I would have imagined as much, but I never looked into it...
Shane
Sure, there is a `make check` target. But you can't test all possible options and results for all possible functions...
Dirk Eddelbuettel