【问题标题】:R specify what week in a monthR指定一个月中的哪一周
【发布时间】:2018-06-05 18:14:21
【问题描述】:

我有一些股票收益每日数据需要转换为每周格式。如您所知,仅在周一至周五进行股票交易,我需要将每天的收益相加以获得累积的每周收益。

我曾考虑过使用 lubridate 的 week 函数,但 lubridate 如何知道一周的开始时间?如何使用工作日功能使 lubridate 识别一周,即“星期一”到“星期五”是一周?

我考虑过写一个循环,例如:如果“星期一”到“星期五”在数据中,那么我会调用这个一周。但是对于第二周,我应该用什么让 R 知道我们正在进入第二周?那么当我们到达年底并且我们有 52 周时,如何重置周数以便我们进入下一年?

这是输出:

dat = structure(list(date = structure(c(4019, 4022, 4023, 4024, 4025, 
4026, 4029, 4030, 4031, 4032, 4033, 4036, 4037, 4038, 4039, 4040, 
4043, 4044, 4045, 4046, 4047, 4050, 4051, 4052, 4053, 4054, 4057, 
4058, 4059, 4060, 4061, 4065, 4066, 4067, 4068, 4071, 4072, 4073, 
4074, 4075), class = "Date"), weekday = c("Friday", "Monday", 
"Tuesday", "Wednesday", "Thursday", "Friday", "Monday", "Tuesday", 
"Wednesday", "Thursday", "Friday", "Monday", "Tuesday", "Wednesday", 
"Thursday", "Friday", "Monday", "Tuesday", "Wednesday", "Thursday", 
"Friday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Tuesday", 
"Wednesday", "Thursday", "Friday", "Monday", "Tuesday", "Wednesday", 
"Thursday", "Friday"), COMP = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
), week = c(1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 
4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 
9, 9), RET = c(-0.005435, 0.040984, -0.015748, -0.021333, 0.002725, 
0.01087, 0.024194, -0.002625, 0.013158, 0.033766, 0, -0.007538, 
-0.005063, 0, -0.002545, 0.015306, 0.017588, -0.007407, 0.024876, 
-0.009709, 0, -0.029412, 0.010101, 0.0075, -0.004963, 0.027431, 
-0.002427, 0.007299, -0.009662, -0.004878, 0.014706, -0.004831, 
0.004854, -0.009662, -0.021951, -0.014963, 0.005063, -0.005038, 
0.010127, 0)), .Names = c("date", "weekday", "COMP", "week", 
"RET"), row.names = c(NA, -40L), class = c("data.table", "data.frame"
))

library(data.table)
setDT(dat)

以下是公司 1 从 1981 年 1 月 2 日到 1981 年 2 月 27 日两个月的每日回报数据。让我们忽略来计算此刻的回报,并首先关注时间。

week 列由 week() 函数生成。如您所见,一周不是我想要的,它从星期三开始,到星期三结束。

weekday 由 weekdays() 函数生成。

我想做例如1981-01-02 作为第 1 周(因为我们这里只有星期五),1981-01-05 到 1981-01-09 作为第 2 周,反之亦然。

【问题讨论】:

  • 您应该在这里查看如何制作可重现的示例以及如何更好地提出问题,以便我们为您提供帮助:) stackoverflow.com/questions/5963269/…
  • 嗨,添加了我的数据框的 dput。谢谢

标签: r datetime data.table lubridate


【解决方案1】:

使用lubridate,您可以使用isoweek 定义星期列。

library(lubridate)
df[, wk := isoweek(date)]

这给了你

#           date   weekday COMP week       RET wk
#  1: 1981-01-02    Friday    1    1 -0.005435  1
#  2: 1981-01-05    Monday    1    1  0.040984  2
#  3: 1981-01-06   Tuesday    1    1 -0.015748  2
#  4: 1981-01-07 Wednesday    1    1 -0.021333  2
#  5: 1981-01-08  Thursday    1    2  0.002725  2
#  6: 1981-01-09    Friday    1    2  0.010870  2
#  7: 1981-01-12    Monday    1    2  0.024194  3
#  8: 1981-01-13   Tuesday    1    2 -0.002625  3
#  9: 1981-01-14 Wednesday    1    2  0.013158  3
# 10: 1981-01-15  Thursday    1    3  0.033766  3
# 11: 1981-01-16    Friday    1    3  0.000000  3
# 12: 1981-01-19    Monday    1    3 -0.007538  4
# 13: 1981-01-20   Tuesday    1    3 -0.005063  4
# 14: 1981-01-21 Wednesday    1    3  0.000000  4
# 15: 1981-01-22  Thursday    1    4 -0.002545  4
# 16: 1981-01-23    Friday    1    4  0.015306  4
# 17: 1981-01-26    Monday    1    4  0.017588  5
# 18: 1981-01-27   Tuesday    1    4 -0.007407  5
# 19: 1981-01-28 Wednesday    1    4  0.024876  5
# 20: 1981-01-29  Thursday    1    5 -0.009709  5

使用 dplyr,您可以添加周列

library(dplyr)
df %>% 
  mutate(wk = isoweek(date))

【讨论】:

  • 您创建了一个新表,我猜它可以与 OP 的表与 left_join(op_data, your_result) 结合起来?
  • 这似乎是最好的解决方案。 OP 的数据没有周六/周日,所以你可以做dt[, wk := isoweek(date)]
  • 它还有以下好处:(a) 数据不需要按日期排序;(b) 即使缺少星期一行,它仍然有效
  • 是的,你是对的@Frank。我对此很陌生,不知何故无法重现 OP 的数据集。
  • @Gabriel isoweek 函数按照您建议的方式计算周数,即使日期缺失/无序也能正常工作。
【解决方案2】:

如果你想从数据集开始算起星期一...

DT[, wk := {
  w = DT[weekday == "Monday"][DT, on=.(date), roll=TRUE, which = TRUE]
  if (anyNA(w)) 
    1L + replace(w, is.na(w), 0L) 
  else 
    w
}]

它是如何工作的

我们正在将DT 的每一行滚动连接到DT 的子集,其中weekday == "Monday" 滚动到子集中的最新日期 (on = .(date), roll = TRUE),并确定我们在子集中的哪些行号登陆(which = TRUE)。

如果第一天不是星期一,我们将缺少值(对于第一个星期一之前的所有天),并且希望将它们替换为 1,并将所有其他行号加一。


哦,我猜还有

DT[, wk := (first(weekday) != "Monday") + cumsum(weekday == "Monday")]

...因为逻辑条件first(weekday) != "Monday" 如果为 FALSE,则为 0,如果为 TRUE,则为 1。

【讨论】:

  • 我宁愿选择使用round.IDate(date, "weeks") 的东西,但我无法理解它的输出...可能是因为这个当前悬而未决的问题github.com/Rdatatable/data.table/issues/2611 或者可能只是因为我没有阅读文档足够仔细。
【解决方案3】:
dat[, wk := .GRP, cut(date, 'week')]
head(dat, 20)

#           date   weekday COMP week       RET wk
#  1: 1981-01-02    Friday    1    1 -0.005435  1
#  2: 1981-01-05    Monday    1    1  0.040984  2
#  3: 1981-01-06   Tuesday    1    1 -0.015748  2
#  4: 1981-01-07 Wednesday    1    1 -0.021333  2
#  5: 1981-01-08  Thursday    1    2  0.002725  2
#  6: 1981-01-09    Friday    1    2  0.010870  2
#  7: 1981-01-12    Monday    1    2  0.024194  3
#  8: 1981-01-13   Tuesday    1    2 -0.002625  3
#  9: 1981-01-14 Wednesday    1    2  0.013158  3
# 10: 1981-01-15  Thursday    1    3  0.033766  3
# 11: 1981-01-16    Friday    1    3  0.000000  3
# 12: 1981-01-19    Monday    1    3 -0.007538  4
# 13: 1981-01-20   Tuesday    1    3 -0.005063  4
# 14: 1981-01-21 Wednesday    1    3  0.000000  4
# 15: 1981-01-22  Thursday    1    4 -0.002545  4
# 16: 1981-01-23    Friday    1    4  0.015306  4
# 17: 1981-01-26    Monday    1    4  0.017588  5
# 18: 1981-01-27   Tuesday    1    4 -0.007407  5
# 19: 1981-01-28 Wednesday    1    4  0.024876  5
# 20: 1981-01-29  Thursday    1    5 -0.009709  5

注意:这与dt[, wk := lubridate::isoweek(date)] 的结果相同,除非数据未按日期排序。在这种情况下,我的解决方案以相同的方式对周进行分组,但 wk 不会按升序排列。第一周可能会收到6 等。

【讨论】:

    【解决方案4】:

    这里有一个更简单的方法(我想更容易理解)来解决这个问题:

    # if its a monday, mark as 1, 2, 3 and so on
    dt[weekday == 'Monday', is_week := seq(.N)]
    
    # forward fill the missing values
    library(zoo)
    dt[, is_week := na.locf(is_week,na.rm = F, fromLast = F)]
    dt[is.na(is_week), is_week := 0]
    
    # find weekly average return
    dt[, mean(RET), is_week]
    
       is_week           V1
    1:       0 -0.005435000
    2:       1  0.003499600
    3:       2  0.013698600
    4:       3  0.000032000
    5:       4  0.005069600
    6:       5  0.002131400
    7:       6 -0.002950222
    8:       7 -0.000962200
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-14
      • 2010-12-20
      • 2011-04-17
      • 1970-01-01
      • 2019-09-04
      • 2021-11-29
      相关资源
      最近更新 更多