Home > OS >  How to get the day of the week from a date and insert the time into another dataset in R
How to get the day of the week from a date and insert the time into another dataset in R

Time:02-15

Here dataset, where is the store opening hours by day of the week

store=structure(list(weekday_code = c("fri", "mon", "sat", "sun", "thu", 
"tue", "wen"), workday_sign = c(1L, 1L, 1L, 1L, 1L, 1L, 1L), 
    opening_time = c("9:00:00", "9:00:00", "9:00:00", "10:00:00", 
    "9:00:00", "9:00:00", "9:00:00"), closing_time = c("18:00:00", 
    "18:00:00", "17:00:00", "16:00:00", "18:00:00", "18:00:00", 
    "18:00:00")), class = "data.frame", row.names = c(NA, -7L
))

the second dataset also has opening_time and closing_time columns (dt_start and dt_end).

wrong=structure(list(kod_dolg = c(50000690L, 801L, 50000690L, 801L, 
50000690L, 801L, 801L, 50000690L, 801L, 50000690L, 50000690L, 
801L, 50000690L, 50000690L, 50000690L, 801L, 50000690L, 801L, 
50000690L, 801L, 50000690L, 801L, 50000690L, 50000690L, 801L, 
801L, 50000690L, 50000690L, 50000690L, 801L, 50000690L, 50000690L, 
50000690L, 801L, 50000690L, 801L, 50000690L), dt_start = c("14.02.2022 12:00", 
"14.02.2022 11:00", "14.02.2022 10:00", "15.02.2022 8:00", "15.02.2022 8:00", 
"15.02.2022 10:00", "15.02.2022 12:00", "15.02.2022 12:00", "16.02.2022 11:00", 
"16.02.2022 12:00", "16.02.2022 13:00", "17.02.2022 10:00", "17.02.2022 10:00", 
"17.02.2022 12:00", "17.02.2022 13:00", "18.02.2022 8:00", "18.02.2022 8:00", 
"18.02.2022 10:00", "18.02.2022 10:00", "18.02.2022 12:00", "18.02.2022 12:00", 
"12.02.2022 10:00", "12.02.2022 13:00", "12.02.2022 12:00", "12.02.2022 12:00", 
"19.02.2022 10:00", "19.02.2022 13:00", "19.02.2022 12:00", "19.02.2022 12:00", 
"20.02.2022 10:00", "20.02.2022 10:00", "20.02.2022 12:00", "20.02.2022 13:00", 
"13.02.2022 10:00", "13.02.2022 10:00", "13.02.2022 12:00", "13.02.2022 12:00"
), dt_end = c("14.02.2022 22:00", "14.02.2022 21:00", "14.02.2022 20:00", 
"15.02.2022 10:00", "15.02.2022 10:00", "15.02.2022 20:00", "15.02.2022 22:00", 
"15.02.2022 22:00", "16.02.2022 21:00", "16.02.2022 22:00", "16.02.2022 20:00", 
"17.02.2022 20:00", "17.02.2022 20:00", "17.02.2022 22:00", "17.02.2022 22:00", 
"18.02.2022 10:00", "18.02.2022 10:00", "18.02.2022 20:00", "18.02.2022 20:00", 
"18.02.2022 22:00", "18.02.2022 22:00", "12.02.2022 20:00", "12.02.2022 20:00", 
"12.02.2022 22:00", "12.02.2022 22:00", "19.02.2022 20:00", "19.02.2022 20:00", 
"19.02.2022 22:00", "19.02.2022 22:00", "20.02.2022 20:00", "20.02.2022 20:00", 
"20.02.2022 22:00", "20.02.2022 22:00", "13.02.2022 20:00", "13.02.2022 20:00", 
"13.02.2022 22:00", "13.02.2022 22:00"), person_number = c(976291L, 
754105L, 867801L, NA, 867801L, NA, NA, 867801L, NA, 976291L, 
938541L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, 
-37L))

In first dataset store there is column weekday_code

fri Friday
mon Monday
sat saturday
sun Sunday
thu Thursday
tue Tuesday
wen wednesday

but in second dataset wrong there is not column weekday_code. So the question how from dates from dt_start and dt_end get weekday? For example 14.02.2022 10:00 is monday. Then the second queustion is how to insert work hours on specific days of the week into wrong dataset from store dataset. Example.In wrong dataset monday dt_start=14.02.2022 12:00 and dt_end=14.02.2022 22:00:00 but in store dataset in monday this shop must work from 9-18. So for each monday date in wrong dataset i must change work hours like that dt_start=14.02.2022 9:00:00 and dt_end=14.02.2022 18:00:00.

Similarly for other days of the week. In other words, i find the date in the wrong, determine its day of the week, look at the open and closing hours for this day of the week in store and insert these hours into the dt_start and dt_end that corresponds to this day of the week.

How can i make such permutations of working hours?

CodePudding user response:

First change the type of dt_start and dt_end to date time, then use lubridate::wday() to find out the weekday. Remember to change all characters to lower case, and change wed to wen to match your store style.

Then left_join it with store and rename it back to your style.

library(lubridate)
library(tidyverse)

wrong_with_weekday <- wrong %>% mutate(dt_start = as_datetime(dt_start, format = "%y.%m.%d"),
                 dt_end = as_datetime(dt_end, format = "%y.%m.%d"),
                 weekday_code = tolower(wday(dt_start, label = T)),
                 weekday_code = gsub("wed", "wen", weekday_code)) %>% 
  select(-dt_start, - dt_end)

left_join(wrong_with_weekday, store, by = "weekday_code") %>% 
  dplyr::rename("dt_start" = "opening_time",
                "dt_end" = "closing_time")

Output

   kod_dolg person_number weekday_code workday_sign dt_start   dt_end
1  50000690        976291          thu            1  9:00:00 18:00:00
2       801        754105          thu            1  9:00:00 18:00:00
3  50000690        867801          thu            1  9:00:00 18:00:00
4       801            NA          fri            1  9:00:00 18:00:00
5  50000690        867801          fri            1  9:00:00 18:00:00
6       801            NA          fri            1  9:00:00 18:00:00
7       801            NA          fri            1  9:00:00 18:00:00
8  50000690        867801          fri            1  9:00:00 18:00:00
9       801            NA          sat            1  9:00:00 17:00:00
10 50000690        976291          sat            1  9:00:00 17:00:00
11 50000690        938541          sat            1  9:00:00 17:00:00
12      801            NA          mon            1  9:00:00 18:00:00
13 50000690            NA          mon            1  9:00:00 18:00:00
14 50000690            NA          mon            1  9:00:00 18:00:00
15 50000690            NA          mon            1  9:00:00 18:00:00
16      801            NA          tue            1  9:00:00 18:00:00
17 50000690            NA          tue            1  9:00:00 18:00:00
18      801            NA          tue            1  9:00:00 18:00:00
19 50000690            NA          tue            1  9:00:00 18:00:00
20      801            NA          tue            1  9:00:00 18:00:00
21 50000690            NA          tue            1  9:00:00 18:00:00
22      801            NA          mon            1  9:00:00 18:00:00
23 50000690            NA          mon            1  9:00:00 18:00:00
24 50000690            NA          mon            1  9:00:00 18:00:00
25      801            NA          mon            1  9:00:00 18:00:00
26      801            NA          wen            1  9:00:00 18:00:00
27 50000690            NA          wen            1  9:00:00 18:00:00
28 50000690            NA          wen            1  9:00:00 18:00:00
29 50000690            NA          wen            1  9:00:00 18:00:00
30      801            NA          thu            1  9:00:00 18:00:00
31 50000690            NA          thu            1  9:00:00 18:00:00
32 50000690            NA          thu            1  9:00:00 18:00:00
33 50000690            NA          thu            1  9:00:00 18:00:00
34      801            NA          wen            1  9:00:00 18:00:00
35 50000690            NA          wen            1  9:00:00 18:00:00
36      801            NA          wen            1  9:00:00 18:00:00
37 50000690            NA          wen            1  9:00:00 18:00:00

CodePudding user response:

The very first thing you'll have to do is, change the data type of dt_start and dt_end to POXIXct. Then you need to create different columns for storing date and time.

Here's how you'll do it:

wrong$dt_start <- as.POSIXct(wrong$dt_start, format = "%d.%m.%Y %H:%M", tz = Sys.timezone())
wrong$opening_time <- format(as.POSIXct(wrong$dt_start), format = "%H:%M")
wrong$dt_start <- as.Date(wrong$dt_start)
wrong <- wrong[, c(1, 2, 5, 3, 4)]

wrong$dt_end <- as.POSIXct(wrong$dt_end, format = "%d.%m.%Y %H:%M", tz = Sys.timezone())
wrong$closing_time <- format(as.POSIXct(wrong$dt_end), format = "%H:%M")
wrong$dt_end <- as.Date(wrong$dt_end)
wrong <- wrong[, c(1, 2, 3, 4, 6, 5)]
wrong$weekday <- weekdays(wrong$dt_start)

I've changed the weekday_code with weekday in order to join the dfs.

new <- c("Friday", "Monday", "Saturday", "Sunday", "Thursday", "Tuesday", "Wednesday")
store$weekday <- new[match(store$weekday, store$weekday_code, nomatch = 0)]
store$weekday_code <- NULL
store <- store[, c(4, 1, 2, 3)]

Then you can left_join the data frames to get the desired result.

library(dplyr)
wrong2 <- wrong %>%
  left_join(store, by = c("weekday")) %>%
  mutate(opening_time = coalesce(opening_time.y, opening_time.x)) %>%
  mutate(closing_time = coalesce(closing_time.y, closing_time.x)) %>%
  select(-opening_time.x, -closing_time.x, -closing_time.y, -opening_time.y)

The output will look like this:

   kod_dolg   dt_start     dt_end person_number   weekday workday_sign
1  50000690 2022-02-14 2022-02-14        976291    Monday            1
2       801 2022-02-14 2022-02-14        754105    Monday            1
3  50000690 2022-02-14 2022-02-14        867801    Monday            1
4       801 2022-02-15 2022-02-15            NA   Tuesday            1
5  50000690 2022-02-15 2022-02-15        867801   Tuesday            1
6       801 2022-02-15 2022-02-15            NA   Tuesday            1
7       801 2022-02-15 2022-02-15            NA   Tuesday            1
8  50000690 2022-02-15 2022-02-15        867801   Tuesday            1
9       801 2022-02-16 2022-02-16            NA Wednesday            1
10 50000690 2022-02-16 2022-02-16        976291 Wednesday            1
11 50000690 2022-02-16 2022-02-16        938541 Wednesday            1
12      801 2022-02-17 2022-02-17            NA  Thursday            1
13 50000690 2022-02-17 2022-02-17            NA  Thursday            1
14 50000690 2022-02-17 2022-02-17            NA  Thursday            1
15 50000690 2022-02-17 2022-02-17            NA  Thursday            1
16      801 2022-02-18 2022-02-18            NA    Friday            1
17 50000690 2022-02-18 2022-02-18            NA    Friday            1
18      801 2022-02-18 2022-02-18            NA    Friday            1
19 50000690 2022-02-18 2022-02-18            NA    Friday            1
20      801 2022-02-18 2022-02-18            NA    Friday            1
21 50000690 2022-02-18 2022-02-18            NA    Friday            1
22      801 2022-02-12 2022-02-12            NA  Saturday            1
23 50000690 2022-02-12 2022-02-12            NA  Saturday            1
24 50000690 2022-02-12 2022-02-12            NA  Saturday            1
25      801 2022-02-12 2022-02-12            NA  Saturday            1
26      801 2022-02-19 2022-02-19            NA  Saturday            1
27 50000690 2022-02-19 2022-02-19            NA  Saturday            1
28 50000690 2022-02-19 2022-02-19            NA  Saturday            1
29 50000690 2022-02-19 2022-02-19            NA  Saturday            1
30      801 2022-02-20 2022-02-20            NA    Sunday            1
31 50000690 2022-02-20 2022-02-20            NA    Sunday            1
32 50000690 2022-02-20 2022-02-20            NA    Sunday            1
33 50000690 2022-02-20 2022-02-20            NA    Sunday            1
34      801 2022-02-13 2022-02-13            NA    Sunday            1
35 50000690 2022-02-13 2022-02-13            NA    Sunday            1
36      801 2022-02-13 2022-02-13            NA    Sunday            1
37 50000690 2022-02-13 2022-02-13            NA    Sunday            1
   opening_time closing_time
1       9:00:00     18:00:00
2       9:00:00     18:00:00
3       9:00:00     18:00:00
4       9:00:00     18:00:00
5       9:00:00     18:00:00
6       9:00:00     18:00:00
7       9:00:00     18:00:00
8       9:00:00     18:00:00
9       9:00:00     18:00:00
10      9:00:00     18:00:00
11      9:00:00     18:00:00
12      9:00:00     18:00:00
13      9:00:00     18:00:00
14      9:00:00     18:00:00
15      9:00:00     18:00:00
16      9:00:00     18:00:00
17      9:00:00     18:00:00
18      9:00:00     18:00:00
19      9:00:00     18:00:00
20      9:00:00     18:00:00
21      9:00:00     18:00:00
22      9:00:00     17:00:00
23      9:00:00     17:00:00
24      9:00:00     17:00:00
25      9:00:00     17:00:00
26      9:00:00     17:00:00
27      9:00:00     17:00:00
28      9:00:00     17:00:00
29      9:00:00     17:00:00
30     10:00:00     16:00:00
31     10:00:00     16:00:00
32     10:00:00     16:00:00
33     10:00:00     16:00:00
34     10:00:00     16:00:00
35     10:00:00     16:00:00
36     10:00:00     16:00:00
37     10:00:00     16:00:00
  • Related