I have a function in R that, given n days, returns a list of the last n weekdays. My solution works fine, but it feels inelegant, and I was wondering if there were any easy ways to improve it.
WeekdayList <- function(n) {
Today <- as.Date(Sys.time())
days <- c(Today)
i <- 1
while (length(days) < n) {
NewDay <- as.Date(Today-i)
if (!weekda开发者_JAVA技巧ys(NewDay) %in% c("Saturday", "Sunday")) {
days <- c(days,NewDay)
}
i <- i+1
}
days
}
WeekdayList(30)
WeekdayList(2)
Exclusion of holidays would be a nice feature too.
Vectorizing code is essential in R. Here is the example:
WeekdayList2 <- function(n) {
Today <- as.Date(Sys.time())
dayz <- seq(Today, Today - 2 * n, "-1 days")
dayz <- dayz[!(weekdays(dayz) %in% c("Saturday", "Sunday"))]
dayz <- dayz[seq_len(n)]
return(dayz)
}
identical(WeekdayList2(1000), WeekdayList(1000))
system.time(WeekdayList2(10000))
system.time(WeekdayList(10000))
[1] TRUE
user system elapsed
0 0 0
user system elapsed
4.90 0.00 4.91
As you can see, even though my function creates a vector twice almost twice the size it needs to be (and then deletes the weekends), it is much faster than using a "for" loop. My computer cannot even run your function with n = 100000
(not that that you'd care about that many days back anyway), but WeekdayList2 runs it almost instantly.
Since Holidays are relative to where you are, you'll probably need to manually upload a list of dates, and add another criteria to filter out those dates from the data.
I added a holiday calculation to Rguy's code.
WeekdayList3 <- function(n) {
library(timeDate)
Today <- as.Date(Sys.time())
dayz <- rev(seq(Today - 2 * n, Today, "days"))
years <- as.numeric(unique(format(dayz,'%Y')))
holidays <- as.Date(holidayNYSE(years))
dayz <- dayz[!(weekdays(dayz) %in% c("Saturday", "Sunday"))]
dayz <- dayz[!(dayz %in% holidays)]
dayz <- dayz[1 : n]
return(dayz)
}
WeekdayList3(100)
精彩评论