首页 > 解决方案 > 使用季度结束日期 (R) 填充数据框列

问题描述

我正在尝试获取我的数据框(ValuationDate)的一列,以根据已经提供的边界日期反映“季度结束”日期(给定年份的 12/31、3/31、6/30、9/30)。

所以,我有一个“索引”列(IDNum)、一个“.id”列(计算 IDNum)和两个日期字段(报告日期和结算日期)。

基本上,给定报告日期和结算日期,我想为这两者之间的每个季度结束日期以及报告和结算日期本身生成记录。

例如:

报告日期:2001-12-29;结算日期:2002-05-31

这应该生成 4 条记录:

  1. 2001-12-29
  2. 2001-12-31
  3. 2002-03-31
  4. 2002-05-31

我已经成功地复制了正确的行数,并且可以在其中获得两个“简单”日期(每条记录的第一个和最后一个),但是在中间日期(“这里发生了什么”部分代码)。

library(zoo)
    ClaimID_sam <- "1x1"
    ReptDat_sam <- strptime("2001-12-29", format = "%Y-%m-%d")
    SettDat_sam <- strptime("2002-05-31", format = "%Y-%m-%d")
    RecordCount <- as.integer((4*(as.yearqtr(SettDat_sam) - as.yearqtr(ReptDat_sam))) + 2)

    sam_DF <- data.frame(ClaimID_sam,ReptDat_sam,SettDat_sam,RecordCount)
    sam_DF <- as.data.frame(lapply(sam_DF,rep,RecordCount))
    sam_DF = getanID(sam_DF,"ClaimID_sam")

    sam_DF$ValDate <- ifelse(sam_DF$.id == 1, 
                                  as.Date(sam_DF$ReptDat_sam),
                                        "WHAT GOES HERE?????") 

    sam_DF$ValDate = ifelse(sam_DF$.id == sam_DF$RecordCount, 
                                  as.Date(sam_DF$SettDat_sam),
                                  sam_DF$ValDate)

编辑 @g-grothendieck 的解决方案几乎是完美的,虽然看到了一些奇怪的东西,但还没有达到四分之一的终点?

   > do.call("rbind", by(ModData, ModData$ClaimID, add_dates))
       ClaimID Loss_Reported_Date settlementDate       ValuationDate
11X1.1    11X1         2001-12-29     2002-05-31 2001-12-29 00:00:00
11X1.2    11X1         2001-12-29     2002-05-31 2001-12-30 18:00:00
11X1.3    11X1         2001-12-29     2002-05-31 2002-03-30 18:00:00
11X1.4    11X1         2001-12-29     2002-05-31 2002-05-31 00:00:00
11X2.1    11X2         2002-04-06     2002-10-04 2002-04-06 00:00:00
11X2.2    11X2         2002-04-06     2002-10-04 2002-06-29 19:00:00
11X2.3    11X2         2002-04-06     2002-10-04 2002-09-29 19:00:00
11X2.4    11X2         2002-04-06     2002-10-04 2002-10-04 00:00:00

标签: rdate

解决方案


假设我们的输入是一个包含 ID、st、en 列的数据框,如下所示。不同 ID 的 st 和 en 值可能不同。

下面的示例对于每个 ID 具有相同的开始日期和相同的结束日期,但代码处理一般情况。

使用 function make_dates,对于每个输入 ID,即对于每一行,都将st和转换enyearqtr类,在它们之间创建一个序列,转换为季度结束日期(frac = 1 表示季度结束),包括standen在其中,确保没有元素超出en并删除重复项。使用 group_by/group_modify 将其应用于每个 ID(即每行),或者在最后我们展示了如何使用 do.call/by 作为替代方案。

library(dplyr)
library(zoo)

# test input
inp <- data.frame(ID = 1:2, st = as.Date("2001-12-29"), en = as.Date("2002-05-31"))

# given dates st & en return a vector of them and intervening qtr ends
make_dates <- function(st, en) {
  st <- as.Date(st)
  en <- as.Date(en)
  yq1 <- as.yearqtr(st)
  yq2 <- as.yearqtr(en)
  dates <- as.Date(seq(yq1, yq2, 1/4), frac = 1)
  unique(pmin(c(st, dates, en), en))
}

inp %>%
  group_by(ID) %>%
  group_modify(~ cbind(., Date = make_dates(st, en))) %>%
  ungroup

给予:

# A tibble: 8 x 4
     ID st         en         Date      
  <int> <date>     <date>     <date>    
1     1 2001-12-29 2002-05-31 2001-12-29
2     1 2001-12-29 2002-05-31 2001-12-31
3     1 2001-12-29 2002-05-31 2002-03-31
4     1 2001-12-29 2002-05-31 2002-05-31
5     2 2001-12-29 2002-05-31 2001-12-29
6     2 2001-12-29 2002-05-31 2001-12-31
7     2 2001-12-29 2002-05-31 2002-03-31
8     2 2001-12-29 2002-05-31 2002-05-31

dplyr 管道可以在没有 dplyr 的情况下交替完成,如下所示:

add_dates <- function(x) with(x, data.frame(ID, st, en, Date = make_dates(st, en)))
do.call("rbind", by(inp, inp$ID, add_dates))

更新

已经更新好几次了。


推荐阅读