How to get week numbers from dates? - r
Looking for a function in R to convert dates into week numbers (of year) I went for week from package data.table.
However, I observed some strange behaviour:
> week("2014-03-16") # Sun, expecting 11
[1] 11
> week("2014-03-17") # Mon, expecting 12
[1] 11
> week("2014-03-18") # Tue, expecting 12
[1] 12
Why is the week number switching to 12 on tuesday, instead of monday? What am I missing? (Timezone should be irrelevant as there are just dates?!)
Other suggestions for (base) R functions are appreciated as well.
Base package Using the function strftime passing the argument %V to obtain the week of the year as decimal number (01–53) as defined in ISO 8601. (More details in the documentarion: ?strftime)
strftime(c("2014-03-16", "2014-03-17","2014-03-18", "2014-01-01"), format = "%V")
Output:
[1] "11" "12" "12" "01"
if you try with lubridate:
library(lubridate)
lubridate::week(ymd("2014-03-16", "2014-03-17","2014-03-18", '2014-01-01'))
[1] 11 11 12 1
The pattern is the same. Try isoweek
lubridate::isoweek(ymd("2014-03-16", "2014-03-17","2014-03-18", '2014-01-01'))
[1] 11 12 12 1
I understand the need for packages in certain situations, but the base language is so elegant and so proven (and debugged and optimized).
Why not:
dt <- as.Date("2014-03-16")
dt2 <- as.POSIXlt(dt)
dt2$yday
[1] 74
And then your choice whether the first week of the year is zero (as in indexing in C) or 1 (as in indexing in R).
No packages to learn, update, worry about bugs in.
Actually, I think you may have discovered a bug in the week(...) function, or at least an error in the documentation. Hopefully someone will jump in and explain why I am wrong.
Looking at the code:
library(lubridate)
> week
function (x)
yday(x)%/%7 + 1
<environment: namespace:lubridate>
The documentation states:
Weeks is the number of complete seven day periods that have occured between the date and January 1st, plus one.
But since Jan 1 is the first day of the year (not the zeroth), the first "week" will be a six day period. The code should (??) be
(yday(x)-1)%/%7 + 1
NB: You are using week(...) in the data.table package, which is the same code as lubridate::week except it coerces everything to integer rather than numeric for efficiency. So this function has the same problem (??).
if you want to get the week number with the year use: "%Y-W%V":
e.g yearAndweeks <- strftime(dates, format = "%Y-W%V")
so
> strftime(c("2014-03-16", "2014-03-17","2014-03-18", "2014-01-01"), format = "%Y-W%V")
becomes:
[1] "2014-W11" "2014-W12" "2014-W12" "2014-W01"
If you want to get the week number with the year, Grant Shannon's solution using strftime works, but you need to make some corrections for the dates around january 1st. For instance, 2016-01-03 (yyyy-mm-dd) is week 53 of year 2015, not 2016. And 2018-12-31 is week 1 of 2019, not of 2018. This codes provides some examples and a solution. In column "yearweek" the years are sometimes wrong, in "yearweek2" they are corrected (rows 2 and 5).
library(dplyr)
library(lubridate)
# create a testset
test <- data.frame(matrix(data = c("2015-12-31",
"2016-01-03",
"2016-01-04",
"2018-12-30",
"2018-12-31",
"2019-01-01") , ncol=1, nrow = 6 ))
# add a colname
colnames(test) <- "date_txt"
# this codes provides correct year-week numbers
test <- test %>%
mutate(date = as.Date(date_txt, format = "%Y-%m-%d")) %>%
mutate(yearweek = as.integer(strftime(date, format = "%Y%V"))) %>%
mutate(yearweek2 = ifelse(test = day(date) > 7 & substr(yearweek, 5, 6) == '01',
yes = yearweek + 100,
no = ifelse(test = month(date) == 1 & as.integer(substr(yearweek, 5, 6)) > 51,
yes = yearweek - 100,
no = yearweek)))
# print the result
print(test)
date_txt date yearweek yearweek2
1 2015-12-31 2015-12-31 201553 201553
2 2016-01-03 2016-01-03 201653 201553
3 2016-01-04 2016-01-04 201601 201601
4 2018-12-30 2018-12-30 201852 201852
5 2018-12-31 2018-12-31 201801 201901
6 2019-01-01 2019-01-01 201901 201901
I think the problem is that the week calculation somehow uses the first day of the year. I don't understand the internal mechanics, but you can see what I mean with this example:
library(data.table)
dd <- seq(as.IDate("2013-12-20"), as.IDate("2014-01-20"), 1)
# dd <- seq(as.IDate("2013-12-01"), as.IDate("2014-03-31"), 1)
dt <- data.table(i = 1:length(dd),
day = dd,
weekday = weekdays(dd),
day_rounded = round(dd, "weeks"))
## Now let's add the weekdays for the "rounded" date
dt[ , weekday_rounded := weekdays(day_rounded)]
## This seems to make internal sense with the "week" calculation
dt[ , weeknumber := week(day)]
dt
i day weekday day_rounded weekday_rounded weeknumber
1: 1 2013-12-20 Friday 2013-12-17 Tuesday 51
2: 2 2013-12-21 Saturday 2013-12-17 Tuesday 51
3: 3 2013-12-22 Sunday 2013-12-17 Tuesday 51
4: 4 2013-12-23 Monday 2013-12-24 Tuesday 52
5: 5 2013-12-24 Tuesday 2013-12-24 Tuesday 52
6: 6 2013-12-25 Wednesday 2013-12-24 Tuesday 52
7: 7 2013-12-26 Thursday 2013-12-24 Tuesday 52
8: 8 2013-12-27 Friday 2013-12-24 Tuesday 52
9: 9 2013-12-28 Saturday 2013-12-24 Tuesday 52
10: 10 2013-12-29 Sunday 2013-12-24 Tuesday 52
11: 11 2013-12-30 Monday 2013-12-31 Tuesday 53
12: 12 2013-12-31 Tuesday 2013-12-31 Tuesday 53
13: 13 2014-01-01 Wednesday 2014-01-01 Wednesday 1
14: 14 2014-01-02 Thursday 2014-01-01 Wednesday 1
15: 15 2014-01-03 Friday 2014-01-01 Wednesday 1
16: 16 2014-01-04 Saturday 2014-01-01 Wednesday 1
17: 17 2014-01-05 Sunday 2014-01-01 Wednesday 1
18: 18 2014-01-06 Monday 2014-01-01 Wednesday 1
19: 19 2014-01-07 Tuesday 2014-01-08 Wednesday 2
20: 20 2014-01-08 Wednesday 2014-01-08 Wednesday 2
21: 21 2014-01-09 Thursday 2014-01-08 Wednesday 2
22: 22 2014-01-10 Friday 2014-01-08 Wednesday 2
23: 23 2014-01-11 Saturday 2014-01-08 Wednesday 2
24: 24 2014-01-12 Sunday 2014-01-08 Wednesday 2
25: 25 2014-01-13 Monday 2014-01-08 Wednesday 2
26: 26 2014-01-14 Tuesday 2014-01-15 Wednesday 3
27: 27 2014-01-15 Wednesday 2014-01-15 Wednesday 3
28: 28 2014-01-16 Thursday 2014-01-15 Wednesday 3
29: 29 2014-01-17 Friday 2014-01-15 Wednesday 3
30: 30 2014-01-18 Saturday 2014-01-15 Wednesday 3
31: 31 2014-01-19 Sunday 2014-01-15 Wednesday 3
32: 32 2014-01-20 Monday 2014-01-15 Wednesday 3
i day weekday day_rounded weekday_rounded weeknumber
My workaround is this function:
https://github.com/geneorama/geneorama/blob/master/R/round_weeks.R
round_weeks <- function(x){
require(data.table)
dt <- data.table(i = 1:length(x),
day = x,
weekday = weekdays(x))
offset <- data.table(weekday = c('Sunday', 'Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday', 'Saturday'),
offset = -(0:6))
dt <- merge(dt, offset, by="weekday")
dt[ , day_adj := day + offset]
setkey(dt, i)
return(dt[ , day_adj])
}
Of course, you can easily change the offset to make Monday first or whatever. The best way to do this would be to add an offset to the offset... but I haven't done that yet.
I provided a link to my simple geneorama package, but please don't rely on it too much because it's likely to change and not very documented.
Using only base, I wrote the following function.
Note:
Assumes Mon is day number 1 in the week
First week is week 1
Returns 0 if week is 52 from last year
Fine-tune to suit your needs.
findWeekNo <- function(myDate){
# Find out the start day of week 1; that is the date of first Mon in the year
weekday <- switch(weekdays(as.Date(paste(format(as.Date(myDate),"%Y"),"01-01", sep = "-"))),
"Monday"={1},
"Tuesday"={2},
"Wednesday"={3},
"Thursday"={4},
"Friday"={5},
"Saturday"={6},
"Sunday"={7}
)
firstMon <- ifelse(weekday==1,1, 9 - weekday )
weekNo <- floor((as.POSIXlt(myDate)$yday - (firstMon-1))/7)+1
return(weekNo)
}
findWeekNo("2017-01-15") # 2
Related
How to make Monthly Predictions in R Facebook Prophet, Data is also Monthly
Data (df3) Looks like this. One "1" for day at the end was added just to fulfill date format requirement. ds y<br/> 1 2015-01-01 -390217.2<br/> 2 2015-02-01 230944.1<br/> 3 2015-03-01 367259.7<br/> 4 2015-04-01 567962.8<br/> 5 2015-05-01 753175.6<br/> 6 2015-06-01 -907767.5<br/> 7 2015-07-01 -52225619.9<br/> 8 2015-08-01 631666.1<br/> 9 2015-09-01 -792896.8<br/> 10 2015-10-01 430847.6<br/> 11 2015-11-01 5159146.7<br/> 12 2015-12-01 -2087233.7 Code i have tried: try <- prophet(df3, seasonality.mode = 'multiplicative') future <- make_future_dataframe(try, periods = 1) forecast <- predict(try, future) tail(forecast) Result i am getting: ds yhat<br/> 50 2019-02-01 -9536258.7<br/> 51 2019-03-01 -456995.5<br/> 52 2019-04-01 -1734330.0<br/> 53 2019-05-01 -3428825.1<br/> 54 2019-06-01 -2612847.0<br/> 55 2019-06-02 -2918161.2 Question is how to predict July 2019 instead of 2nd june 2019 value?
future = prophet.make_future_dataframe(periods=12 , freq='M') for more information https://towardsdatascience.com/forecasting-in-python-with-facebook-prophet-29810eb57e66
future = prophet.make_future_dataframe(periods=12 , freq='MS') forecast = prophet.predict(future) fig = prophet.plot(forecast) fig.show() MS stands for Month Start.
How to insert missing dates/times using R based on criteria?
A data frame like below. 3 staffs have hourly readings in days, but incomplete (every staff shall have 24 readings a day). Understand that staffs had different number of readings on the days. Now only interested in the staff with most readings in the day. There are many days. It’s wanted to insert the missing (hourly) rows for the most ones on the days. That is, 2018-03-02 to insert only for Jack’s, 2018-03-03 only for David and 2018-03-04 only for Kate. I tried these lines from this question (even though they fill all without differentiation) but not getting there. How can it be done in R? date_time <- c("2/3/2018 0:00","2/3/2018 1:00","2/3/2018 2:00","2/3/2018 3:00","2/3/2018 5:00","2/3/2018 6:00","2/3/2018 7:00","2/3/2018 8:00","2/3/2018 9:00","2/3/2018 10:00","2/3/2018 11:00","2/3/2018 12:00","2/3/2018 13:00","2/3/2018 14:00","2/3/2018 16:00","2/3/2018 17:00","2/3/2018 18:00","2/3/2018 19:00","2/3/2018 21:00","2/3/2018 22:00","2/3/2018 23:00","3/3/2018 0:00","3/3/2018 0:00","3/3/2018 1:00","3/3/2018 2:00","3/3/2018 4:00","3/3/2018 5:00","3/3/2018 7:00","3/3/2018 8:00","3/3/2018 9:00","3/3/2018 11:00","3/3/2018 12:00","3/3/2018 14:00","3/3/2018 15:00","3/3/2018 17:00","3/3/2018 18:00","3/3/2018 20:00","3/3/2018 22:00","3/3/2018 23:00","4/3/2018 0:00","4/3/2018 0:00","4/3/2018 1:00","4/3/2018 2:00","4/3/2018 3:00","4/3/2018 5:00","4/3/2018 6:00","4/3/2018 7:00","4/3/2018 8:00","4/3/2018 10:00","4/3/2018 11:00","4/3/2018 12:00","4/3/2018 14:00","4/3/2018 15:00","4/3/2018 16:00","4/3/2018 17:00","4/3/2018 19:00","4/3/2018 20:00","4/3/2018 22:00","4/3/2018 23:00") staff <- c("Jack","Jack","Kate","Jack","Jack","Jack","Jack","Jack","Jack","Jack","Jack","Jack","Kate","Jack","Jack","Jack","David","David","Jack","Kate","David","David","David","David","David","David","David","David","David","David","David","David","David","David","David","David","David","Jack","Kate","David","David","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Kate","Jack") reading <- c(7.5,8.3,7,6.9,7.1,8.1,8.4,8.8,6,7.1,8.9,7.3,7.4,6.9,11.3,18.8,4.6,6.7,7.7,7.8,7,7,6.6,6.8,6.7,6.1,7.1,6.3,7.2,6,5.8,6.6,6.5,6.4,7.2,8.4,6.5,6.5,5.5,6.7,7,7.5,6.5,7.5,7.2,6.3,7.3,8,7,8.2,6.5,6.8,7.5,7,6.1,5.7,6.7,4.3,6.3) df <- data.frame(date_time, staff, reading)
The option would be to do this separately. Create a data.table of the dates of interest and the corresponding 'staff', and get the full sequence of date time, then we rbind this with the original dataset and using a condition, we summarise the data library(data.table) stf <- c("Jack", "David", "Kate") date <- as.Date(c("2018-03-02", "2018-03-03", "2018-03-04")) df1 <- data.table(date, staff= stf)[, .(date_time = seq(as.POSIXct(paste(date, "00:00:00"), tz = "GMT"), length.out = 24, by = "1 hour")), staff] setDT(df)[, date_time := as.POSIXct(date_time, "%d/%m/%Y %H:%M", tz = "GMT")] res <- rbindlist(list(df, df1), fill = TRUE)[, .(reading = if(any(is.na(reading))) sum(reading, na.rm = TRUE) else reading), .(staff, date_time)] table(res$staff, as.Date(res$date_time)) # 2018-03-02 2018-03-03 2018-03-04 # David 3 24 2 # Jack 24 1 1 # Kate 3 1 24 head(res) # staff date_time reading #1: Jack 2018-03-02 00:00:00 7.5 #2: Jack 2018-03-02 01:00:00 8.3 #3: Kate 2018-03-02 02:00:00 7.0 #4: Jack 2018-03-02 03:00:00 6.9 #5: Jack 2018-03-02 05:00:00 7.1 #6: Jack 2018-03-02 06:00:00 8.1 tail(res) # staff date_time reading #1: Kate 2018-03-04 04:00:00 0 #2: Kate 2018-03-04 09:00:00 0 #3: Kate 2018-03-04 13:00:00 0 #4: Kate 2018-03-04 18:00:00 0 #5: Kate 2018-03-04 21:00:00 0 #6: Kate 2018-03-04 23:00:00 0
Try this code: Identify each daily hour and all staff members date_h<-seq(as.POSIXlt(min(date_time),format="%d/%m/%Y %H:%M"),as.POSIXlt(max(date_time),format="%d/%m/%Y %H:%M"),by=60*60) staff_u<-unique(staff) comb<-expand.grid(staff_u,date_h) colnames(comb)<-c("staff","date_time") Uniform date format in df df$date_time<-as.POSIXlt(df$date_time,format="%d/%m/%Y %H:%M") Merge information out<-merge(comb,df,all.x=T) Your output: head(out) staff date_time reading 1 Jack 2018-03-02 00:00:00 7.5 2 Jack 2018-03-02 01:00:00 8.3 3 Jack 2018-03-02 02:00:00 NA 4 Jack 2018-03-02 03:00:00 6.9 5 Jack 2018-03-02 04:00:00 NA 6 Jack 2018-03-02 05:00:00 7.1
R : how to get the rolling mean of a variable over the last few days but only at a given hour?
Consider this time <- seq(ymd_hms("2014-02-24 23:00:00"), ymd_hms("2014-06-25 08:32:00"), by="hour") group <- rep(LETTERS[1:20], each = length(time)) value <- sample(-10^3:10^3,length(time), replace=TRUE) df2 <- data.frame(time,group,value) str(df2) > head(df2) time group value 1 2014-02-24 23:00:00 A 246 2 2014-02-25 00:00:00 A -261 3 2014-02-25 01:00:00 A 628 4 2014-02-25 02:00:00 A 429 5 2014-02-25 03:00:00 A -49 6 2014-02-25 04:00:00 A -749 I would like to create a variable that contains, for each group, the rolling mean of value over the last 5 days (not including the current observation) only considering observations that fall at the exact same hour as the current observation. In other words: At time 2014-02-24 23:00:00, df2['rolling_mean_same_hour'] contains the mean of the values of value observed at 23:00:00 during the last 5 days in the data (not including 2014-02-24 of course). I would like to do that in either dplyr or data.table. I confess having no ideas how to do that. Any ideas? Many thanks!
You can calculate the rollmean() with your data grouped by the group variable and hour of the time variable, normally the rollmean() will include the current observation, but you can use shift() function to exclude the current observation from the rollmean: library(data.table); library(zoo) setDT(df2) df2[, .(rolling_mean_same_hour = shift( rollmean(value, 5, na.pad = TRUE, align = 'right'), n = 1, type = 'lag'), time), .(hour(time), group)] # hour group rolling_mean_same_hour time # 1: 23 A NA 2014-02-24 23:00:00 # 2: 23 A NA 2014-02-25 23:00:00 # 3: 23 A NA 2014-02-26 23:00:00 # 4: 23 A NA 2014-02-27 23:00:00 # 5: 23 A NA 2014-02-28 23:00:00 # --- #57796: 22 T -267.0 2014-06-20 22:00:00 #57797: 22 T -389.6 2014-06-21 22:00:00 #57798: 22 T -311.6 2014-06-22 22:00:00 #57799: 22 T -260.0 2014-06-23 22:00:00 #57800: 22 T -26.8 2014-06-24 22:00:00
R find last weekday of month
How do I find the last weekday (e.g., Wednesday) of the month using R? In the code below, I calculate the month, day of the month, week of the month, and weekday. There are 5 Wednesdays in January 2014, but only 4 Wednesdays in February 2014, so I cannot use max(week of the month) as a filter. Any help is appreciated although I prefer to use the base R functions. DF <- data.frame(DATE = seq(as.Date("2014-01-01"), as.Date("2014-12-31"), "day")) DF$MONTH <- as.numeric(format(DF$DATE, "%m")) DF$DAY_OF_MONTH <- as.numeric(format(DF$DATE, "%d")) DF$WEEK_OF_MONTH <- ceiling(as.numeric(format(DF$DATE, "%d")) / 7) DF$WEEKDAY <- format(DF$DATE, "%A") DF
I think this is what you're after: DF$last_weekday_o_month <- ave( weekdays(DF$DATE), months(DF$DATE), FUN = function(x) tail(x[ !(x %in% c("Saturday","Sunday")) ], 1) ) To find the particular date that is the last weekday.... DF$last_weekdaydate_o_month <- ave( DF$DATE, months(DF$DATE), FUN = function(x) tail(x[ !(weekdays(x) %in% c("Saturday","Sunday")) ], 1) ) the result looks like... DATE last_weekday_o_month last_weekdaydate_o_month 1 2014-01-01 Friday 2014-01-31 2 2014-01-02 Friday 2014-01-31 3 2014-01-03 Friday 2014-01-31 4 2014-01-04 Friday 2014-01-31 5 2014-01-05 Friday 2014-01-31 6 2014-01-06 Friday 2014-01-31 ... 360 2014-12-26 Wednesday 2014-12-31 361 2014-12-27 Wednesday 2014-12-31 362 2014-12-28 Wednesday 2014-12-31 363 2014-12-29 Wednesday 2014-12-31 364 2014-12-30 Wednesday 2014-12-31 365 2014-12-31 Wednesday 2014-12-31 If you did this first, of course you could compute last_weekday_o_month as weekdays(last_weekdaydate_o_month). With a couple packages, this can be done more elegantly/readably, as suggested by #RichardScriven: library(data.table) setDT(DF)[, last_weekdaydate_o_month := last(DATE[!chron::is.weekend(DATE)]) , by = month(DATE)] which gives DATE last_weekdaydate_o_month 1: 2014-01-01 2014-01-31 2: 2014-01-02 2014-01-31 3: 2014-01-03 2014-01-31 4: 2014-01-04 2014-01-31 5: 2014-01-05 2014-01-31 --- 361: 2014-12-27 2014-12-31 362: 2014-12-28 2014-12-31 363: 2014-12-29 2014-12-31 364: 2014-12-30 2014-12-31 365: 2014-12-31 2014-12-31
Here is a method using dplyr. Essentially you group by the month, filter out the 'weekend' days and return the weekday of the last (i.e. max) day. library(dplyr) DF <- data.frame(DATE = seq(as.Date("2014-01-01"), as.Date("2014-12-31"), "day")) DF %>% mutate(month = months(DATE), weekday = weekdays(DATE)) %>% group_by(month) %>% filter(!weekday %in% c("Saturday", "Sunday")) %>% summarise(last_weekday = weekdays(max(DATE))) Source: local data frame [12 x 2] month last_weekday 1 April Wednesday 2 August Friday 3 December Wednesday 4 February Friday 5 January Friday 6 July Thursday 7 June Monday 8 March Monday 9 May Friday 10 November Friday 11 October Friday 12 September Tuesday
library(lubridate) x <- seq(as.Date("2007-12-31"), by="1 day", length.out=(Sys.Date() - as.Date("2007-12-31"))) library(plyr) df <- data.frame(date=x, year=year(x), month=month(x)) df[,"weekday"] <- weekdays(df[,"date"]) df<- df[! df[,"weekday"] %in% c("Saturday", "Sunday"),] df <- ddply(df, .(year, month), summarize, last=max(date))
Produce weekly average plots from large dataset in R
I am quite new to R and have been struggling with trying to convert my data and could use some much needed help. I have a dataframe which is approx. 70,000*2. This data covers a whole year (52 weeks/365 days). A portion of it looks like this: Create.Date.Time Ticket.ID 1 2013-06-01 12:59:00 INCIDENT684790 2 2013-06-02 07:56:00 SERVICE684793 3 2013-06-02 09:39:00 SERVICE684794 4 2013-06-02 14:14:00 SERVICE684796 5 2013-06-02 17:20:00 SERVICE684797 6 2013-06-03 07:20:00 SERVICE684799 7 2013-06-03 08:02:00 SERVICE684839 8 2013-06-03 08:04:00 SERVICE684841 9 2013-06-03 08:04:00 SERVICE684842 10 2013-06-03 08:08:00 SERVICE684843 I am trying to get the number of tickets in every hour of the week (that is, hour 1 to hour 168) for each week. Hour 1 would start on Monday at 00.00, and hour 168 would be Sunday 23.00-23.59. This would be repeated for each week. I want to use the Create.Date.Time data to calculate the hour of the week the ticket is in, say for: 2013-06-01 12:59:00 INCIDENT684790 - hour 133, 2013-06-03 08:08:00 SERVICE684843 - hour 9 I am then going to do averages for each hour and plot those. I am completely at a loss as to where to start. Could someone please point me to the right direction?
Before addressing the plotting aspect of your question, is this the format of data you are trying to get? This uses the package lubridate which you might have to install (install.packages("lubridate",dependencies=TRUE)). library(lubridate) ## Events <- paste( sample(c("INCIDENT","SERVICE"),20000,replace=TRUE), sample(600000:900000,20000) ) t0 <- as.POSIXct( "2013-01-01 00:00:00", format="%Y-%m-%d %H:%M:%S", tz="America/New_York") Dates <- sort(t0 + sample(0:(3600*24*365-1),20000)) Weeks <- week(Dates) wDay <- wday(Dates,label=TRUE) Hour <- hour(Dates) ## hourShift <- function(time,wday){ hShift <- sapply(wday, function(X){ if(X=="Mon"){ 0 } else if(X=="Tues"){ 24*1 } else if(X=="Wed"){ 24*2 } else if(X=="Thurs"){ 24*3 } else if(X=="Fri"){ 24*4 } else if(X=="Sat"){ 24*5 } else { 24*6 } }) ## tOut <- hour(time) + hShift + 1 return(tOut) } ## weekHour <- hourShift(time=Dates,wday=wDay) ## Data <- data.frame( Event=Events, Timestamp=Dates, Week=Weeks, wDay=wDay, dayHour=Hour, weekHour=weekHour, stringsAsFactors=FALSE) ## This gives you: > head(Data) Event Timestamp Week wDay dayHour weekHour 1 SERVICE 783405 2013-01-01 00:13:55 1 Tues 0 25 2 INCIDENT 860015 2013-01-01 01:06:41 1 Tues 1 26 3 INCIDENT 808309 2013-01-01 01:10:05 1 Tues 1 26 4 INCIDENT 835509 2013-01-01 01:21:44 1 Tues 1 26 5 SERVICE 769239 2013-01-01 02:04:59 1 Tues 2 27 6 SERVICE 762269 2013-01-01 02:07:41 1 Tues 2 27