Is there any way to categorize the time (HH:MM)?

62 Views Asked by At

I need to write the meal timings according to day time. For example, between 05:00-10:59 will be categorized as "Breakfast", 11:00-16:59 as "Lunch", 17:00-22:59 as "Dinner" and 23:00-04:59 as "Night. I create the HH:MM data via "for loop" so the data was saved as character. When I used as.POSIXct or strptime function, it was converted again as 'date-time and tz'. I also couldn't use as.numeric or as.double functions. Because the data was like "23:21"

I want to categorize 235 (i in 14:248) different times as meal time. First of all I wrote "for loop" DATA_TIME's output is like that "19/12/2019 20:43"

Time <- character()
for (i in 14:248){
  DATE_TIME <- unlist(strsplit(lines[i], split= "\t"))[1]
  TIME <- unlist(strsplit(DATE_TIME, split=" "))[2]
  Time <- c(Time,TIME)
}

"Time" output is like that "20:43" I tried for that;

for (i in 14:248){
  DATE_TIME <- unlist(strsplit(lines[i], split= "\t"))[1]
  TIME <- unlist(strsplit(DATE_TIME, split=" "))[2]
  H_M <- as.POSIXct(TIME, format="%H:%M")
  h_m <- ifelse(H_M>='05:00' & H_M<'10:59', "Breakfast")
}
h_m
Time
if (Time>='05:00' & Time<'10:59'){
  print("Breakfast")
} else if (Time>='11:00' & Time<'16:59'){
  print("Lunch")
} else if (Time>='17:00' & Time<'22:59'){
  print("Lunch")
} else if (Time>='23:00' & Time<'04:59'){
  print("Night")
}
2

There are 2 best solutions below

0
Rui Barradas On BEST ANSWER

With package chron, coerce the vector of times to class "times" and findInterval will give an index into a vector of cut points.

First, make up some data.

set.seed(2023)
x <- cbind(hour = sample(0:23, 10, TRUE), min = sample(0:59, 10, TRUE))
x <- apply(x, 1, \(y) sprintf("%02d:%02d", y[1], y[2]))
x
#>  [1] "20:28" "15:48" "14:16" "08:04" "07:07" "18:33" "11:02" "01:14" "16:44"
#> [10] "00:03"

Created on 2023-03-30 with reprex v2.0.2

Now the vector of cut points and their labels. And get the intervals where the data falls into.

library(chron)

cutpoint <- c("00:00:00", "5:00:00", "11:00:00", "17:00:00", "23:00:00")
cutpoint <- times(cutpoint)
cutpoint_names <- c("Night", "Breakfast", "Lunch", "Lunch", "Night")

tt <- times(paste0(x, ":00"))
i <- findInterval(tt, cutpoint)
cutpoint_names[i]
#>  [1] "Lunch"     "Lunch"     "Lunch"     "Breakfast" "Breakfast" "Lunch"    
#>  [7] "Lunch"     "Night"     "Lunch"     "Night"

Created on 2023-03-30 with reprex v2.0.2

2
jay.sf On

Using cut.

dat <- transform(dat, 
                 label=cut(as.numeric(strftime(time, '%H')), c(0, 5, 11, 17, 23, 24), right=FALSE,
                           include.lowest=TRUE, labels=c('Night', 'Breakfast', 'Lunch', 'Dinner', 'Night')))

Gives

(showing only the interesting subset)

tm <- strftime(dat$time, '%M') %in% c('00', '59') & strftime(dat$time, '%H') %in% sprintf('%02d', c(0, 4, 5, 10, 11, 16, 17, 22, 23, 24))
dat[tm, ]
#                     time       hour     label
# 1    2023-03-30 00:00:00 0.91480604     Night
# 60   2023-03-30 00:59:00 0.51441293     Night
# 241  2023-03-30 04:00:00 0.06763682     Night
# 300  2023-03-30 04:59:00 0.03251748     Night
# 301  2023-03-30 05:00:00 0.48376814 Breakfast
# 360  2023-03-30 05:59:00 0.47050063 Breakfast
# 601  2023-03-30 10:00:00 0.49815659 Breakfast
# 660  2023-03-30 10:59:00 0.31217965 Breakfast
# 661  2023-03-30 11:00:00 0.77239931     Lunch
# 720  2023-03-30 11:59:00 0.67369296     Lunch
# 961  2023-03-30 16:00:00 0.41075482     Lunch
# 1020 2023-03-30 16:59:00 0.29892941     Lunch
# 1021 2023-03-30 17:00:00 0.86756875    Dinner
# 1080 2023-03-30 17:59:00 0.10035423    Dinner
# 1321 2023-03-30 22:00:00 0.27452580    Dinner
# 1380 2023-03-30 22:59:00 0.98297916    Dinner
# 1381 2023-03-30 23:00:00 0.19006293     Night
# 1440 2023-03-30 23:59:00 0.32297455     Night
# 1441 2023-03-31 00:00:00 0.62878623     Night

Data:

set.seed(42)
dat <- data.frame(time=seq.POSIXt(as.POSIXct('2023-03-30'), as.POSIXct('2023-03-31'), 'min'))
dat$hour <- runif(nrow(dat))