首页 > 解决方案 > 将季度行扩展到多个月行

问题描述

我有一个数据集,其中有一列引用日期。日期以季度的方式书写(即以每 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 万行这样的行,所以我正在寻找一些又快又脏的东西。

任何答复表示赞赏。

标签: rdatedata.tablereshapelubridate

解决方案


更新:根据@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

zoo::as.yearmon@G.Grothendieck 之前的答案建议使用https://stackoverflow.com/a/47634838/3358272,以便将日期保持为每个月的最后一天。)


推荐阅读