Reputation: 3450
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?
Upvotes: 2
Views: 421
Reputation: 270065
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)]
Upvotes: 1
Reputation: 27782
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
Upvotes: 1
Reputation: 70336
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:
Upvotes: 3