I have this vector in a data frame of times in the format of hours:minutes that I want converted to categorical times of day:
time <- c(\"15:03\", \"0
time <- as.POSIXct(strptime(c("15:03", "08:01", "11:59", "23:47", "14:20"),"%H:%M"),"UTC")
x=as.POSIXct(strptime(c("050000","105959","110000","155959","160000",
"185959"),"%H%M%S"),"UTC")
library(tidyverse)
case_when(
between(time,x[1],x[2]) ~"morning",
between(time,x[3],x[4]) ~"afternoon",
between(time,x[5],x[6]) ~"evening",
TRUE ~"night")
[1] "afternoon" "morning" "afternoon" "night" "afternoon"
Using base R:
time <- as.POSIXct(strptime(c("15:03", "08:01", "11:59", "23:47", "14:20"),"%H:%M"),"UTC")
x=as.POSIXct(strptime(c("000000","050000","110000","160000","190000","235959"),
"%H%M%S"),"UTC")
labs=c("night","morning","afternoon","evening","night")
labs[findInterval(time,x)]
[1] "afternoon" "morning" "afternoon" "night" "afternoon"
Using some regex
and ifelse
df$hour <- as.numeric(gsub("\\:.*$", "", df$time))
df$cat <- with(df, ifelse(hour >= 5 & hour<=11, "morning",
ifelse(hour>11 & hour<=16, "evening", "night")))
df
time hour cat
1 15:03 15 evening
2 08:01 8 morning
3 11:59 11 morning
4 23:47 23 night
5 14:20 14 evening
I was able to use an ifelse
statement to make the categories. I changed the strptime
to as.POSIXct
and only kept the hour to make the groups. In the df there are 3 columns representing the original time, just the hour, and then the group. You can change it to be a factor with as.factor
if the category needs to be a factor.
time <- c("15:03", "08:01", "11:59", "23:47", "14:20")
time2 <- format(as.POSIXct(time, tz = "" , format = "%H: %M"), "%H")
df <- data.frame(time, time2 = as.numeric(time2))
df$time_category <- ifelse(df$time2 >= 05 & df$time2 <= 11, "Morning",
ifelse(df$time2 > 11 & df$time2 <= 16, "Afternoon",
ifelse(df$time2 > 16 & df$time2 <= 19, "Evening", "Night")))
I think this gets it done, I'm not sure how to get cut to acept duplicate labels, but maybe someone else will. The key was to use chron::times()
to create a chronological object instead of a datetime object.
time <- c("15:03", "08:01", "11:59", "23:47", "14:20")
timep <- as.POSIXct(time, format = "%H:%M") %>% format("%H:%M:%S")
cut(chron::times(timep) , breaks = (1/24) * c(0,5,11,16,19,24),
labels = c("night", "morning", "afternoon", "evening", "night1"))
# [1] afternoon morning afternoon night1 afternoon
# Levels: night morning afternoon evening night1
tod <- cut(chron::times(timep) , breaks = (1/24) * c(0,5,11,16,19,24))
c("night","morning","afternoon","evening","night")[as.numeric(tod)]
# "afternoon" "morning" "afternoon" "night" "afternoon"
This one is similar to @Onyambu, only using plyr
's mapvalues()
and lubridate
's hour()
:
library(lubridate)
library(plyr)
df$timeofdat<- mapvalues(hour(df$time),from=c(0:23),
to=c(rep("night",times=5), rep("morning",times=6),rep("afternoon",times=5),rep("night", times=8)))