d = seq(as.Date("2018-01-01"),Sys.Date(),by='day')
saturdayList = d[weekdays(d)=='Saturday']
How to get the 2nd and 4th saturday of a month from above list of Saturday dates?
You can split the vector into a list and extract the 2nd and 4th element per month:
lapply(split(saturdayList, format(saturdayList, "%Y-%m")), `[`, c(2, 4))
# $`2018-01`
# [1] "2018-01-13" "2018-01-27"
#
# $`2018-02`
# [1] "2018-02-10" "2018-02-24"
#
# $`2018-03`
# [1] "2018-03-10" "2018-03-24"
#
# $`2018-04`
# [1] "2018-04-14" "2018-04-28"
# ...
Without NA's:
lapply(split(saturdayList, format(saturdayList, "%Y-%m")), function(x)
na.omit(x[c(2,4)]))
Assumptions:
data.table
solution
The solution is slower (on the sample data), than the 'lapply-solution' from docendo discimus. However, it is very flexible, and will alsoperform quite well on larger data-sets.
library(data.table)
#build a data.table out of the vector
DT <- data.table(date = d)
#group by month, select the second and 4 row where wday == 7 (i.e. Saturday)
DT[ DT[ , .I[wday(date) == 7][c(2,4)], by = .(month(date)) ]$V1 ]
output
# date
# 1: 2018-01-13
# 2: 2018-01-27
# 3: 2018-02-10
# 4: 2018-02-24
# 5: 2018-03-10
# 6: 2018-03-24
# 7: 2018-04-14
# 8: 2018-04-28
# 9: 2018-05-12
# 10: 2018-05-26
# 11: 2018-06-09
# 12: 2018-06-23
# 13: 2018-07-14
# 14: 2018-07-28
# 15: 2018-08-11
# 16: 2018-08-25
# 17: 2018-09-08
# 18: 2018-09-22
# 19: 2018-10-13
# 20: 2018-10-27
# 21: 2018-11-10
# 22: 2018-11-24
# 23: 2018-12-08
# 24: 2018-12-22
# date
1) This calculates a vector of 2nd and 4th Saturdays directly from d
although we could replace d
with saturdayList
and it would still work.
Define nextsat
, based on nextfri
in the zoo quickref vignette , which gives the next Saturday on or after the input date for each element of the input vector. Then for each element of d
find the first of the month, apply nextsat
to give the first Saturday of the month and add 7 to get the second Saturday of each month. Add 14 to get the 4th Saturday and sort into a single vector. No packages are used.
nextsat <- function(x) 7 * ceiling(as.numeric(x-6+4) / 7) +
as.Date(6-4, origin = "1970-01-01")
sat2 <- unique(nextsat(as.Date(cut(d, "month")))) + 7
sort(c(sat2, sat2 + 14))
giving:
[1] "2018-01-13" "2018-01-20" "2018-02-10" "2018-02-17" "2018-03-10"
[6] "2018-03-17" "2018-04-14" "2018-04-21" "2018-05-12" "2018-05-19"
[11] "2018-06-09" "2018-06-16" "2018-07-14" "2018-07-21" "2018-08-11"
[16] "2018-08-18" "2018-09-08" "2018-09-15" "2018-10-13" "2018-10-20"
[21] "2018-11-10" "2018-11-17" "2018-12-08" "2018-12-15" "2019-01-12"
[26] "2019-01-19" "2019-02-09" "2019-02-16" "2019-03-09" "2019-03-16"
2) This computes a vector satno
giving the number of each Saturday within its month and then picks off the second and fourth. This also does not use any packages.
satno <- ave(as.numeric(saturdayList), cut(saturdayList, "month"), FUN = seq_along)
saturdayList[satno %in% c(2, 4)]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.