Zach
Zach

Reputation: 30331

Calculate the last n weekdays

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 (!weekdays(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.

Upvotes: 3

Views: 238

Answers (2)

Rguy
Rguy

Reputation: 1652

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.

Upvotes: 6

Zach
Zach

Reputation: 30331

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)

Upvotes: 4

Related Questions