I need help writing a function to count the number of holidays within a time period using lubridate in R

Viewed 195

I am attempting to write a function that counts the number of holidays a person worked in my organization between their start and term date in the year 2017. My organization recognized 6 holidays that year-

New Years Day- 2017-01-02

Memorial Day- 2017-05-29

Independence Day - 2017-07-04

Labor Day - 2017-09-04

Thanksgiving Day- 2017-11-23

Christmas day - 2017-12-25

I used lubridate to combine my year-month-day columns into complete dates using lubridate and dyplr like so:

dates<- data %>% mutate("Term Date" = make_date(month = `Term Month`,
                                                day =  data$`Term Day`,
                                                year =data$`Term Year`),
                       "Start Date"= make_date(month = data$`Start Month`,
                                                day = data$`Start Day`,
                                                year = data$`Start Year`))

I then went on to attempt to write my function.

holidays <- function(x){
  z<- 0
  if( ymd("2017-01-01") %within% interval(dates$`Start Date`, dates$`Term Date`)){
    z <- z + 1
  }
  print(z)
}

This was only my first step. My goal was to first make my function work for new years and then continue to build in other holidays step by step using if statements.I was unable to get the apply function to work correctly and am unsure if my function even works. I attempted to apply the function like so :

apply(dates,2,holidays)

But got an error argument.

Does anyone have any advice?

1 Answers

Putting the holidays in a vector:

holidays <- as.Date(c('2017-01-02', '2017-05-29', '2017-07-04', '2017-09-04', '2017-11-23', '2017-12-25'))

Extracting month and day (to make it independent of year), "%j" stands for day of year:

holidays <- format(as.Date(holidays), "%j")

Generating some random data to test (1000 uniformly distributed work entries in 2017, 5 employees):

d <- data.frame(
  'date' = as.Date(as.integer(runif(1000, 17167, 17531)), origin = '1970-01-01'),
  'emp' = sample(LETTERS[1:5], 1000, replace = T)
)

Filtering out the holidays:

h <- d[format(d$date, "%j") %in% holidays, ]

Counting number of holidays worked per employee using aggregate():

aggregate(h$date, list(h$emp), length)

#  Group.1 x
#1       A 3
#2       B 4
#3       C 2
#4       D 5
#5       E 1

NB: will work for 2017, but won't work for leap years (one workaround that doesn't involve altering the code too too much is to change the year in the holiday vector manually).

Related