R test for morning rush hour - time vector in interval
Question
I'm trying to create a clean function in R to return TRUE/FALSE if a vector of POSIXlt times are in morning rush hour, i.e. 7.30am to 9.30am Monday to Friday. This is what I've done so far, but it seems a bit long and convoluted. Is it possible to improve on this while keeping the code itself readable?
library(lubridate)
morning.rush.hour <- function(tm) {
# between 7.30am and 9.30am Monday to Friday
# vectorised...
# HARDCODED times here!
tm.mrh.start <- update(tm, hour=7, minute=30, second=0)
tm.mrh.end <- update(tm, hour=9, minute=30, second=0)
mrh <- new_interval(tm.mrh.start, tm.mrh.end)
# HARDCODED weekdays here!
((tm$wday %in% 1:5) & # a weekday?
(tm %within% mrh))
}
# for test purposes...
# nb I'm forcing UTC to avoid the error message "Error in as.POSIXlt.POSIXct(x, tz) : invalid 'tz' value"
# - bonus points for solving this too :-)
tm <- with_tz(as.POSIXlt(as.POSIXlt('2012-07-15 00:00:01', tz='UTC') + (0:135)*3000), 'UTC')
data.frame(tm, day=wday(tm, label=TRUE, abbr=FALSE), morning.rush.hour(tm))
Even better if there is a clean function definition for weekday time ranges like this, as I also have evening rush hour, and daytime which is not rush hour and finally not any of these!
Solution
I would do something way simpler than that using difftime
and cut
. You can do the following (using base
functions):
morning.rush.hour<-function(tm){
difftime(tm, cut(tm, breaks="days"), units="hours") -> dt #This is to transform the time of day into a numeric (7:30 and 9:30 being respectively 7.5 and 9.5)
(tm$wday %in% 1:5) & (dt <= 9.5) & (dt >= 7.5) #So: Is it a weekday, it is before 9:30 and is it after 7:30?
}
Edit: You can also add a time-zone parameter to difftime
if needed:
difftime(tm, cut(tm, breaks="days"), units="hours", tz="UTC")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow