Convert Time Object to Categorical (Morning, Afternoon, Evening, Night) Variable in R

Label day timing into morning, afternoon and evening in R

You can achieve this with lubridate and cut.

library(lubridate)

# transform into date time column (if it is not already one)
df$Time_stamp <- ymd_hms(df$Time_stamp)

# create breaks
breaks <- hour(hm("00:00", "6:00", "12:00", "18:00", "23:59"))
# labels for the breaks
labels <- c("Night", "Morning", "Afternoon", "Evening")

df$Time_of_day <- cut(x=hour(df$Time_stamp), breaks = breaks, labels = labels, include.lowest=TRUE)

df

Id Time_stamp Time_of_day
1 3083188c 2016-08-29 13:10:51 Afternoon
2 924d500e 2016-08-29 09:22:33 Morning
3 ad4dd7ff 2016-08-25 20:29:35 Evening

data:

df <- structure(list(Id = c("3083188c", "924d500e", "ad4dd7ff"), 
Time_stamp = c("2016-08-29 13:10:51", "2016-08-29 09:22:33", "2016-08-25 20:29:35")),
.Names = c("Id","Time_stamp"),
class = "data.frame",
row.names = c(NA, -3L))

Grouping of data with certain criteria

Convert VisitTime to POSIXct format, extract hour from it, define "Morning", "Afternoon", "Evening" and "Night" and assign labels.

library(dplyr)

df %>%
mutate(time = as.POSIXct(VisitTime, format = "%H:%M"),
hour = as.integer(format(time, '%H')),
Label = case_when(between(hour, 6, 11) ~ "Morning",
between(hour, 12, 15) ~"Afternoon",
between(hour, 16, 19) ~"Evening",
TRUE ~"Night"))

How to separate data into morning and afternoon

First split:

library(dplyr)

DQ <-
DQ |>
mutate(morning = format(as.POSIXct(Start.time, format = "%m-%d-%y %H:%M:%S"), "%H") < 12) |>
group_by(morning) |>
group_split()

Output:

[[1]]
# A tibble: 2 × 6
ID Date Start.time Completion.time Email morning
<int> <chr> <chr> <chr> <chr> <lgl>
1 4 2022-02-28 2-28-22 23:19:36 2-28-22 23:21:52 anonymous FALSE
2 6 2022-03-01 3-1-22 21:04:49 3-1-22 21:06:31 anonymous FALSE

[[2]]
# A tibble: 4 × 6
ID Date Start.time Completion.time Email morning
<int> <chr> <chr> <chr> <chr> <lgl>
1 1 2022-02-15 2-15-22 11:15:43 2-15-22 11:16:59 anonymous TRUE
2 2 2022-02-25 2-25-22 8:52:33 2-25-22 8:55:02 anonymous TRUE
3 3 2022-02-25 2-25-22 8:55:08 2-25-22 16:16:37 anonymous TRUE
4 5 2022-03-01 3-1-22 8:58:31 3-1-22 9:00:02 anonymous TRUE

Then save:

library(readr)

write_csv(DQ[[1]], "afternoon.csv")
write_csv(DQ[[2]], "morning.csv")

Get part of day (morning, afternoon, evening, night) in Python dataframe

Use cut or custom function with and and also changed < to > and > to <= and also for each value add return:

prods = pd.DataFrame({'hour':range(1, 25)})

b = [0,4,8,12,16,20,24]
l = ['Late Night', 'Early Morning','Morning','Noon','Eve','Night']
prods['session'] = pd.cut(prods['hour'], bins=b, labels=l, include_lowest=True)

def f(x):
if (x > 4) and (x <= 8):
return 'Early Morning'
elif (x > 8) and (x <= 12 ):
return 'Morning'
elif (x > 12) and (x <= 16):
return'Noon'
elif (x > 16) and (x <= 20) :
return 'Eve'
elif (x > 20) and (x <= 24):
return'Night'
elif (x <= 4):
return'Late Night'

prods['session1'] = prods['hour'].apply(f)
print (prods)
hour session session1
0 1 Late Night Late Night
1 2 Late Night Late Night
2 3 Late Night Late Night
3 4 Late Night Late Night
4 5 Early Morning Early Morning
5 6 Early Morning Early Morning
6 7 Early Morning Early Morning
7 8 Early Morning Early Morning
8 9 Morning Morning
9 10 Morning Morning
10 11 Morning Morning
11 12 Morning Morning
12 13 Noon Noon
13 14 Noon Noon
14 15 Noon Noon
15 16 Noon Noon
16 17 Eve Eve
17 18 Eve Eve
18 19 Eve Eve
19 20 Eve Eve
20 21 Night Night
21 22 Night Night
22 23 Night Night
23 24 Night Night

How to create a day/night factor from POSIXct variable

Data

library(data.table)

SightingTime_chr = c("2017-07-31 09:56:27 UTC", "2017-07-31 10:36:30 UTC", "2017-08-01 00:07:20 UTC","2017-08-01 01:31:00 UTC", "2017-08-01 10:38:23 UTC", "2017-08-01 21:13:06 UTC", "2017-08-02 15:13:30 UTC", "2017-08-02 18:05:28 UTC", "2017-08-02 21:04:08 UTC")
x = data.table(SightingTime_chr)

Code

A couple of things were not quite right with your conversion to datetime (the format for example):

x$SightingTime = as.POSIXct(x$SightingTime_chr, format = "%Y-%m-%d %H:%M:%S", tz = "UTC")
attributes(x$SightingTime)$tzone <- "America/Halifax"

I would first convert the character strings to POSIXct and then convert to the America/Halifax timezone as the original vector seems to be in UTC datetime (omit the second step if I#m wrong).

x$TOD <- format(x$SightingTime, format="%H%M%S")

x$daynight = with(x, ifelse(TOD > "053000" & TOD < "200000", "Day", "Night"))

I convert the time of day to a pseudo-numeric value (the values are not technically correct but this should be enough for the comparison purpose).

x$daynight
[1] "Day" "Day" "Night" "Night" "Day" "Day" "Day" "Day" "Day"

Now the results appear correct.

Alternative

From this answer we can get an elegant solution in case we want mor than just night/day:

nightday <- function(datetime) {
paste(
c("Night", "Morning", "Afternoon", "Evening", "Night")[
cut(as.numeric(format(datetime, "%H%M")), c(0, 530, 1100, 1700 ,2000, 2359))
]
)
}
nightday(x$SightingTime)
[1] "Morning" "Morning" "Night" "Night" "Morning" "Evening" "Afternoon" "Afternoon" "Evening"

Cut day into multiple parts

Turn timestamp to the POSIXlt object and extract hour of time by the $ symbol.

da$daypart <- as.POSIXlt(da$timestamp)$hour + 1

# timestamp daypart
# 1 2016-01-24 01:17:37 GMT 2
# 2 2016-01-24 02:09:41 GMT 3
# 3 2016-01-24 13:34:35 GMT 14
# 4 2016-01-24 15:17:56 GMT 16
# 5 2016-01-24 18:14:55 GMT 19

Edit: Split time into 48 parts

time <- as.POSIXlt(da$timestamp)
da$daypart48 <- time$hour * 2 + (time$min > 30) + 1
da

# timestamp daypart daypart48
# 1 2016-01-24 01:17:37 GMT 2 3
# 2 2016-01-24 02:09:41 GMT 3 5
# 3 2016-01-24 13:34:35 GMT 14 28
# 4 2016-01-24 15:17:56 GMT 16 31
# 5 2016-01-24 18:14:55 GMT 19 37

Displaying morning, afternoon, or evening to user based on time using variables

If you are linking the javascript file before the span, then
Uncaught TypeError: Cannot set property 'innerHTML' of null at master.js:13 will occur since it can't find the span yet. Try:

window.onload = function(e){ 
document.getElementById("time").innerHTML = time;
}


Related Topics



Leave a reply



Submit