将季度行扩展为多个月度行

Expand quarterly rows to multiple monthly rows

我有一个数据集,其中有一列引用日期。日期按季度书写(即每3个月为1个单位)。 一栏表明日期实际上是每季度还是每月。我只想处理季度类型。

我想将每季度的行扩展为 3 个月的行。另一列称为“收益”的列也将受到影响,应除以“3”(即一个季度中的月数)。

示例:

example <- data.frame(quarterly_reports = as.Date(as.character(c(20200331,20200630, 20200930,20201231, 20210131)), "%Y%m%d"),
                      type = c("q","q","q","q","m"),
                      gains = c(18000, 30000, 45000, 60000, 10000))

这是它的样子:

  quarterly_reports type gains
1        2020-03-31    q 18000
2        2020-06-30    q 30000
3        2020-09-30    q 45000
4        2020-12-31    q 60000
5        2021-01-31    m 10000

我想要的是与此类似的输出(并注意我如何将增益列除以 3):

   quarterly_reports type gains
1         2020-01-31    m  6000
2         2020-02-28    m  6000
3         2020-03-31    m  6000
4         2020-04-30    m 10000
5         2020-05-31    m 10000
6         2020-06-30    m 10000
7         2020-07-31    m 15000
8         2020-08-31    m 15000
9         2020-09-30    m 15000
10        2020-10-31    m 20000
11        2020-11-30    m 20000
12        2020-12-31    m 20000
13        2021-01-31    m 10000

注意:我正在使用 data.table,并且我正在尝试利用 lubridate 将日期从季度转换为月度。我有大约 300 万行,所以我正在寻找快速而肮脏的东西。

如有任何回复,我们将不胜感激。

更新:根据@Henrik 的建议,这里有一个更有效的替代方案:

library(lubdridate)
newexample <- example[type == 'q', .(
  quarterly_reports = quarterly_reports %m-% months(rep(0:2, .N)),
  type = "m",
  gains = gains/3) ]
setorder(newexample, quarterly_reports)
newexample
#     quarterly_reports   type gains
#                <Date> <char> <num>
#  1:        2020-01-31      m  6000
#  2:        2020-02-29      m  6000
#  3:        2020-03-31      m  6000
#  4:        2020-04-30      m 10000
#  5:        2020-05-30      m 10000
#  6:        2020-06-30      m 10000
#  7:        2020-07-30      m 15000
#  8:        2020-08-30      m 15000
#  9:        2020-09-30      m 15000
# 10:        2020-10-31      m 20000
# 11:        2020-11-30      m 20000
# 12:        2020-12-31      m 20000

(这可能要慢得多,为后代保留。)

我不知道这在 data.table 的正常引用语义方面为您节省了很多效率,因为它必须创建很多行(我认为这不是在 -地方)。无论哪种方式,

library(zoo)
library(data.table)
setDT(example)

newexample <- example[type == "q",][,rn:=seq_len(nrow(.SD))][, .(
  quarterly_reports = as.Date(seq(as.yearmon(quarterly_reports), length.out = 3, by = -1/12), frac = 1),
  type = rep("m", 3),
  gains = rep(gains, 3) / 3
), by = rn ][,rn:=NULL]
newexample <- rbindlist(list(newexample, example[type != "q",]))
setorder(newexample, "quarterly_reports")
newexample[]
#     quarterly_reports   type gains
#                <Date> <char> <num>
#  1:        2020-01-31      m  6000
#  2:        2020-02-29      m  6000
#  3:        2020-03-31      m  6000
#  4:        2020-04-30      m 10000
#  5:        2020-05-31      m 10000
#  6:        2020-06-30      m 10000
#  7:        2020-07-31      m 15000
#  8:        2020-08-31      m 15000
#  9:        2020-09-30      m 15000
# 10:        2020-10-31      m 20000
# 11:        2020-11-30      m 20000
# 12:        2020-12-31      m 20000
# 13:        2021-01-31      m 10000

(@G.Grothendieck 之前的回答 建议使用 zoo::as.yearmon,以便将日期保留为每个月的最后一天。)