Search code examples
rsubsetxts

How to subset xts object by end of quarter dates by sequence number?


I'm trying to extract end-of-quarter data from a large xts object based on the numerical location and I'm at a loss. Any help would be greatly appreciated. As an example, let's say I have a year of data as follows:

set.seed(78)
date.a <-seq(as.Date("2000/1/1"), as.Date("2000/12/31"), "days")
dat <-xts(rnorm(length(date.a)), date.a)

head(dat)
                 [,1]
2000-01-01  0.7172775
2000-01-02  0.2581460
2000-01-03  1.0750581
2000-01-04 -0.5375775
2000-01-05 -1.3264418
2000-01-06  1.1817348

I can easily extract end-of-quarter dat manually, such as:

a <-dat[91]
b <-dat[182]  
c <-dat[274]
d <-dat[366]

c(a,b,c,d)
                 [,1]
2000-03-31  0.7329080
2000-06-30  1.0648634
2000-09-30 -3.1556240
2000-12-31  0.9452281

How can I programatically extract these dates/data? The challenge is figuring out how the numerical sequence plays out over the course of several years or decades. Since the interval isn't going to be a standard ~91 days, it's unclear how to proceed. Any suggestions? Thanks!


Solution

  • You can create a vector of dates d and refer to the xts elements as dat[d].

    Here's how I would do it (I like to use the lubridate package, and I like to emulate the EOMonth function from Excel):

    library(lubridate)
    EOMonth = function(d, step) {
      day(d) = 1 # just in case we inadvertantly compute 30 February or 31 April.
      month(d) = month(d) + step
      day(d) = days_in_month(d)
      return(d)
    }
    d = EOMonth(ymd("1999-12-31"), seq(from = 3, to = 12, by = 3))
    dat[d]
    

    If you need the indices, you could then do something like this:

    all.d = ymd("1999-12-31") + 1:366
    answer = which(all.d %in% d)