如何按序列号在季度末日期对 xts 对象进行子集化?

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

我正在尝试根据数字位置从大型 xts 对象中提取季度末数据,但我不知所措。任何帮助将不胜感激。例如,假设我有一年的数据如下:

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

我可以轻松地手动提取季度末数据,例如:

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

如何以编程方式提取这些 dates/data?挑战在于弄清楚数字序列在几年或几十年的过程中如何发挥作用。由于间隔不会是标准的 ~91 天,因此不清楚如何进行。有什么建议么?谢谢!

您可以创建日期向量 d 并将 xts 元素引用为 dat[d]

我会这样做(我喜欢使用 lubridate 包,我喜欢从 Excel 中模拟 EOMonth 函数):

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]

如果你需要索引,你可以这样做:

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

您可以将日期转换为 zoo::yearqtr。然后在设置 frac = 1 时将 yearqtr 转换回 Date,即每个季度的最后日期(参见 ?yearmon)。使用这些日期对您的数据进行子集化:

dat[index(dat) == as.Date(as.yearqtr(index(dat)), frac = 1)]
#                 [,1]
# 2000-03-31  0.7329080
# 2000-06-30  1.0648634
# 2000-09-30 -3.1556240
# 2000-12-31  0.9452281