6

Build an xts object with two rows.

library(xts)   
junk<-xts(c(1,2),as.Date(c("2010-01-01","2010-05-01")))   
junk   
>            [,1]
> 2010-01-01    1   
> 2010-05-01    2   

Why doesn't the following change the index for the first row?

time(junk[1])<-as.Date("2010-02-01")   
junk   
>            [,1]
> 2010-01-01    1   
> 2010-05-01    2   

I realize that the following works, but why doesn't the above work?

time(junk)[1]<-as.Date("2010-02-01")   
junk   
>            [,1]
> 2010-02-01    1   
> 2010-05-01    2   

Thanks,
Bill

Bill S
  • 61
  • 1
  • 2

3 Answers3

6

Direct answer to the post is that the magic is inside of attr<- as Josh says. Subsetting the object first simply creates a new object that gets promptly disposed of once time<- is finished.

In addition you can see the 'internals' of the index via the .index() function. Essentially an vector of type double or integer that maps to POSIXct time - with some attributes attached. The class you are assigning is automatically coerced back and forth. This makes the internals easier to maintain - and lets you do things with any time class you need outside of it.

In general, Date will be the cleanest way to keep TZ and secs trouble out of the mix, but keep in mind that the cost of this hidden aspect is the function index(). This will have to recreate the object you expect.

Jeff R
  • 829
  • 4
  • 5
3
time(junk[1]) <- as.Date("2010-02-01") 

The above doesn't change the index of the first row of junk because subsetting creates a new object--with no reference to junk--and time<-.xts replaces the index of the new object.

Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
  • 2
    Except there is a time<-.xts method. It's not visible but does show up with methods(`time<-`). – IRTFM Dec 14 '10 at 03:13
  • @Dwin good catch. I was looking at `time`, not `time<-`. That's what I get for posting right before bed. – Joshua Ulrich Dec 14 '10 at 11:13
  • That makes sense. Also, in the time(junk)[1] statement (the last chunk of code), is a new subset object created that references junk? And, that reference forces junk to be modified? – Bill S Dec 14 '10 at 18:52
  • @Bill `time(junk)` returns the index attribute of `junk`; and I'm not familiar enough with R's parse/eval rules on object attributes to be able to tell you for sure what `attr<-` is actually doing... but it could be something like what you mention. – Joshua Ulrich Dec 15 '10 at 20:36
2

The dates in time series are not referenced with "[". They are more like rownames in dataframes. They are stored in the "index" leaf of the attributes list. In addition to that, they are not of Date class but rather the DateTime class so you need to may use POSIXct:

> attributes(junk)$index[1] <- as.POSIXct("2010-02-01")
> junk
           [,1]
2010-02-01    1
2010-05-01    2

Edit: more accurately the attribute$index is internally in seconds but the time method will accept a variety of assignment classes.

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • I'll remember that attributes function. I'm still working on that methods("time<-") thing. Is it a good idea for me to use as.POSIXct() rather than as.Date()? Most of my time data will be daily or monthly data (minute and second requirements are rare, but possible). – Bill S Dec 14 '10 at 18:59
  • In this case it is not needed, since there is a time<- function. That means that the class of the object being assigned is first assessed and when it of class Date that it will get properly multiplied by 24*60*60 and an offset applied before getting stuffed into the internal representation which is in seconds. – IRTFM Dec 15 '10 at 17:45