确定日期序列中的第三个星期五
Identify 3rd Friday in a sequence of Dates
下面的代码有一个日期列表,如果日期是该月的最后一天,对于数据集中的所有日期(不在日历上),那么它将日期标记为该月的最后一天月
data = data.frame(day = seq(as.Date("2014-01-01"),as.Date("2016-05-10"),"day"), weekday = weekdays ( seq(as.Date("2014-01-01"),as.Date("2016-05-10"),"day")))
excludeDays <- c("Saturday", "Sunday")
data <- subset(data, !weekdays(data$day) %in% excludeDays) #exclude weekend
setDT(data)
data[, LastDayInMonth := day == max(day), by = list(year(day),month(day) )]
head(data,100)
我还需要在数据中添加一个标记 (TRUE/FALSE) 任何星期五的列,即该月的第 3 个星期五。有什么想法吗?
例如 2014-01-17、2014-02-21、......2014-05-16 等......是第三个星期五。
谢谢。
试试这个 - 没有 data.table:
library(lubridate)
library(dplyr)
data <- data.frame(day = seq(as.Date("2014-01-01"),
as.Date("2016-05-10"),"day"),
weekday = weekdays(seq(as.Date("2014-01-01"),
as.Date("2016-05-10"),"day")))
data$year_month <- floor_date(data$day, unit = 'month')
fri3 <- filter(data, weekday == 'Friday') %>%
group_by(year_month) %>% slice(3)
data$Third_Fri <- data$day %in% fri3$day
您可以稍后删除 year_month
另一种方法:
data[, is3Friday:=cumsum(weekday=="Friday"), by=substring(day, 1, 7)]
data[, is3Friday:=ifelse(weekday=="Friday" & is3Friday==3, TRUE, FALSE)]
data[is3Friday==TRUE]
day weekday LastDayInMonth is3Friday
1: 2014-01-17 Friday FALSE TRUE
2: 2014-02-21 Friday FALSE TRUE
3: 2014-03-21 Friday FALSE TRUE
4: 2014-04-18 Friday FALSE TRUE
5: 2014-05-16 Friday FALSE TRUE
6: 2014-06-20 Friday FALSE TRUE
data[, numWeek := 1:.N, by = .(year(day), month(day), weekday)]
data[numWeek == 3 & weekday == "Friday"]
或添加为列:
data[, is3rdFriday := numWeek == 3 & weekday == "Friday"]
如果您要查找日历中的第 3 个星期五,而不是数据中的第 3 个星期五,那么您可以做得更简单:
data[, is3rdFriday := (mday(day) - 1) %/% 7 + 1 == 3 & weekday == "Friday"]
要涵盖数据在月中开始时的极端情况,您可以尝试这样做:
occ <- 3L # 3rd occurrence of selected weekday
data[, ThirdFridayInMonth := weekday == "Friday" &
as.integer(day - lubridate::floor_date(day, "month")) %/% 7L + 1L == occ]
这也适用于该月的其他工作日,例如,在每个第一个星期一进行标记。
编辑: 要求的解释。
基本思路是每个月的第一个星期五必须是每个月的前 7 天之一,第二个星期五必须是第 8 到 14 天之一,依此类推。因此,lubridate::floor_date(day, "month")
计算出 day
所在月份的第一天。现在,您构建一个需要转换为 integer
的 difftime
对象的差异.如果 day
恰好是一个月的第一天,则为 0
。现在你使用整数除法 %/%
其中 returns 0 代表一个月的前 7 天,1 代表第二个 7 天,等等。然后通过添加 1.
进行调整
编辑 2: 改进代码
在写解释的时候,我认识到代码可以进一步改进。
我们可以直接使用月中的第几天,这样可以避免计算日期差异和随后的整数转换:
data[, ThirdFridayInMonth := weekday == "Friday" &
(mday(day) - 1) %/% 7L + 1L == occ]
在这里,我使用 mday
(data.table
包的一部分)而不是 as.integer(format(day, "%d"))
。
下面的代码有一个日期列表,如果日期是该月的最后一天,对于数据集中的所有日期(不在日历上),那么它将日期标记为该月的最后一天月
data = data.frame(day = seq(as.Date("2014-01-01"),as.Date("2016-05-10"),"day"), weekday = weekdays ( seq(as.Date("2014-01-01"),as.Date("2016-05-10"),"day")))
excludeDays <- c("Saturday", "Sunday")
data <- subset(data, !weekdays(data$day) %in% excludeDays) #exclude weekend
setDT(data)
data[, LastDayInMonth := day == max(day), by = list(year(day),month(day) )]
head(data,100)
我还需要在数据中添加一个标记 (TRUE/FALSE) 任何星期五的列,即该月的第 3 个星期五。有什么想法吗?
例如 2014-01-17、2014-02-21、......2014-05-16 等......是第三个星期五。
谢谢。
试试这个 - 没有 data.table:
library(lubridate)
library(dplyr)
data <- data.frame(day = seq(as.Date("2014-01-01"),
as.Date("2016-05-10"),"day"),
weekday = weekdays(seq(as.Date("2014-01-01"),
as.Date("2016-05-10"),"day")))
data$year_month <- floor_date(data$day, unit = 'month')
fri3 <- filter(data, weekday == 'Friday') %>%
group_by(year_month) %>% slice(3)
data$Third_Fri <- data$day %in% fri3$day
您可以稍后删除 year_month
另一种方法:
data[, is3Friday:=cumsum(weekday=="Friday"), by=substring(day, 1, 7)]
data[, is3Friday:=ifelse(weekday=="Friday" & is3Friday==3, TRUE, FALSE)]
data[is3Friday==TRUE]
day weekday LastDayInMonth is3Friday
1: 2014-01-17 Friday FALSE TRUE
2: 2014-02-21 Friday FALSE TRUE
3: 2014-03-21 Friday FALSE TRUE
4: 2014-04-18 Friday FALSE TRUE
5: 2014-05-16 Friday FALSE TRUE
6: 2014-06-20 Friday FALSE TRUE
data[, numWeek := 1:.N, by = .(year(day), month(day), weekday)]
data[numWeek == 3 & weekday == "Friday"]
或添加为列:
data[, is3rdFriday := numWeek == 3 & weekday == "Friday"]
如果您要查找日历中的第 3 个星期五,而不是数据中的第 3 个星期五,那么您可以做得更简单:
data[, is3rdFriday := (mday(day) - 1) %/% 7 + 1 == 3 & weekday == "Friday"]
要涵盖数据在月中开始时的极端情况,您可以尝试这样做:
occ <- 3L # 3rd occurrence of selected weekday
data[, ThirdFridayInMonth := weekday == "Friday" &
as.integer(day - lubridate::floor_date(day, "month")) %/% 7L + 1L == occ]
这也适用于该月的其他工作日,例如,在每个第一个星期一进行标记。
编辑: 要求的解释。
基本思路是每个月的第一个星期五必须是每个月的前 7 天之一,第二个星期五必须是第 8 到 14 天之一,依此类推。因此,lubridate::floor_date(day, "month")
计算出 day
所在月份的第一天。现在,您构建一个需要转换为 integer
的 difftime
对象的差异.如果 day
恰好是一个月的第一天,则为 0
。现在你使用整数除法 %/%
其中 returns 0 代表一个月的前 7 天,1 代表第二个 7 天,等等。然后通过添加 1.
编辑 2: 改进代码
在写解释的时候,我认识到代码可以进一步改进。
我们可以直接使用月中的第几天,这样可以避免计算日期差异和随后的整数转换:
data[, ThirdFridayInMonth := weekday == "Friday" &
(mday(day) - 1) %/% 7L + 1L == occ]
在这里,我使用 mday
(data.table
包的一部分)而不是 as.integer(format(day, "%d"))
。