Alex
Alex

Reputation: 2788

Define custom days in R

I would like to define the times at which a day starts and ends.

For example, lets assume that I don't want a new day to start until 10am the following day.

For sample data I have the following:

                    dt
1  2015-01-01 10:45:00
2  2015-01-01 11:30:00
3  2015-01-01 11:45:00
4  2015-01-01 12:00:00
5  2015-01-01 12:30:00
6  2015-01-01 13:00:00
7  2015-01-01 14:30:00
8  2015-01-01 15:00:00
9  2015-01-01 16:30:00
10 2015-01-01 16:45:00
11 2015-01-01 18:15:00
12 2015-01-01 18:45:00
13 2015-01-01 19:15:00
14 2015-01-01 21:45:00
15 2015-01-01 22:00:00
16 2015-01-01 23:00:00
17 2015-01-01 23:15:00
18 2015-01-02 00:00:00
19 2015-01-02 11:45:00
20 2015-01-02 17:00:00
21 2015-01-02 18:00:00
22 2015-01-02 19:15:00
23 2015-01-02 21:30:00
24 2015-01-02 21:45:00
25 2015-01-02 22:45:00

A dput() of this data can be copied into R.

data <- structure(list(dt = structure(c(1420111800, 1420127100, 1420129800, 
1420133400, 1420149600, 1420150500, 1420154100, 1420155900, 1420157700, 
1420200000, 1420203600, 1420206300, 1420209000, 1420215300, 1420218000, 
1420224300, 1420229700, 1420231500, 1420234200, 1420236900, 1420239600, 
1420240500, 1420241400, 1420244100, 1420245900), class = c("POSIXct", 
"POSIXt"), tzone = "UTC")), row.names = c(NA, -25L), class = "data.frame")

The only way I have calcualted the day of week in the past is with lubridate::wday as follows

data %>% 
  mutate(dow = wday(dt, label = T))

                    dt dow
1  2015-01-01 11:30:00 Thu
2  2015-01-01 15:45:00 Thu
3  2015-01-01 16:30:00 Thu
4  2015-01-01 17:30:00 Thu
5  2015-01-01 22:00:00 Thu
6  2015-01-01 22:15:00 Thu
7  2015-01-01 23:15:00 Thu
8  2015-01-01 23:45:00 Thu
9  2015-01-02 00:15:00 Fri # make Thu
10 2015-01-02 12:00:00 Fri
11 2015-01-02 13:00:00 Fri 
12 2015-01-02 13:45:00 Fri 
13 2015-01-02 14:30:00 Fri 
14 2015-01-02 16:15:00 Fri 
15 2015-01-02 17:00:00 Fri 
16 2015-01-02 18:45:00 Fri 
17 2015-01-02 20:15:00 Fri
18 2015-01-02 20:45:00 Fri
19 2015-01-02 21:30:00 Fri
20 2015-01-02 22:15:00 Fri
21 2015-01-02 23:00:00 Fri
22 2015-01-02 23:15:00 Fri
23 2015-01-02 23:30:00 Fri
24 2015-01-03 00:15:00 Sat # make Fri
25 2015-01-03 00:45:00 Sat # make Fri

I marked the days that would be incorrect if assuming a new day does not start until 10am the next day.

I was curious what options are available for defining the times for which a new day starts/ends.

Upvotes: 1

Views: 121

Answers (3)

Pablo Rod
Pablo Rod

Reputation: 669

Using base

data$dow <- with(data, ifelse(strftime(dt, "%H") < 11, 
                  strftime(dt - as.difftime(1, units = "days"), "%a"), 
                  strftime(dt, "%a")
                  )
     )

Upvotes: 1

Zhiqiang Wang
Zhiqiang Wang

Reputation: 6769

I wonder if this will get you there:

data %>% 
  mutate(
    dt1 = dt - hours(10),
    dow = wday(dt1, label = T))

                    dt                 dt1 dow
1  2015-01-01 11:30:00 2015-01-01 01:30:00 Thu
2  2015-01-01 15:45:00 2015-01-01 05:45:00 Thu
3  2015-01-01 16:30:00 2015-01-01 06:30:00 Thu
4  2015-01-01 17:30:00 2015-01-01 07:30:00 Thu
5  2015-01-01 22:00:00 2015-01-01 12:00:00 Thu
6  2015-01-01 22:15:00 2015-01-01 12:15:00 Thu
7  2015-01-01 23:15:00 2015-01-01 13:15:00 Thu
8  2015-01-01 23:45:00 2015-01-01 13:45:00 Thu
9  2015-01-02 00:15:00 2015-01-01 14:15:00 Thu
10 2015-01-02 12:00:00 2015-01-02 02:00:00 Fri
11 2015-01-02 13:00:00 2015-01-02 03:00:00 Fri
12 2015-01-02 13:45:00 2015-01-02 03:45:00 Fri
13 2015-01-02 14:30:00 2015-01-02 04:30:00 Fri
14 2015-01-02 16:15:00 2015-01-02 06:15:00 Fri
15 2015-01-02 17:00:00 2015-01-02 07:00:00 Fri
16 2015-01-02 18:45:00 2015-01-02 08:45:00 Fri
17 2015-01-02 20:15:00 2015-01-02 10:15:00 Fri
18 2015-01-02 20:45:00 2015-01-02 10:45:00 Fri
19 2015-01-02 21:30:00 2015-01-02 11:30:00 Fri
20 2015-01-02 22:15:00 2015-01-02 12:15:00 Fri
21 2015-01-02 23:00:00 2015-01-02 13:00:00 Fri
22 2015-01-02 23:15:00 2015-01-02 13:15:00 Fri
23 2015-01-02 23:30:00 2015-01-02 13:30:00 Fri
24 2015-01-03 00:15:00 2015-01-02 14:15:00 Fri
25 2015-01-03 00:45:00 2015-01-02 14:45:00 Fri

Upvotes: 0

r2evans
r2evans

Reputation: 160607

Lacking timezone changes, I'd think your best bet is to if_else off of the hour of the day, similar to what you're doing now:

library(dplyr)
library(lubridate)
data %>%
  mutate(
    dow = wday(dt, label = T),
    dow2 = wday(dt - if_else(hour(dt) < 11, 86400, 0), label = TRUE)
  )
#                     dt dow dow2
# 1  2015-01-01 11:30:00 Thu  Thu
# 2  2015-01-01 15:45:00 Thu  Thu
# 3  2015-01-01 16:30:00 Thu  Thu
# 4  2015-01-01 17:30:00 Thu  Thu
# 5  2015-01-01 22:00:00 Thu  Thu
# 6  2015-01-01 22:15:00 Thu  Thu
# 7  2015-01-01 23:15:00 Thu  Thu
# 8  2015-01-01 23:45:00 Thu  Thu
# 9  2015-01-02 00:15:00 Fri  Thu
# 10 2015-01-02 12:00:00 Fri  Fri
# 11 2015-01-02 13:00:00 Fri  Fri
# 12 2015-01-02 13:45:00 Fri  Fri
# 13 2015-01-02 14:30:00 Fri  Fri
# 14 2015-01-02 16:15:00 Fri  Fri
# 15 2015-01-02 17:00:00 Fri  Fri
# 16 2015-01-02 18:45:00 Fri  Fri
# 17 2015-01-02 20:15:00 Fri  Fri
# 18 2015-01-02 20:45:00 Fri  Fri
# 19 2015-01-02 21:30:00 Fri  Fri
# 20 2015-01-02 22:15:00 Fri  Fri
# 21 2015-01-02 23:00:00 Fri  Fri
# 22 2015-01-02 23:15:00 Fri  Fri
# 23 2015-01-02 23:30:00 Fri  Fri
# 24 2015-01-03 00:15:00 Sat  Fri
# 25 2015-01-03 00:45:00 Sat  Fri

(This if_else is rather trivial and can be shortened to wday(dt - 86400*(hour(dt) < 11), label = TRUE).)

Upvotes: 2

Related Questions