Convert time object to categorical (morning, after

2019-05-15 23:01发布

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", "08:01", "11:59", "23:47", "14:20")
    df$time <- format(strptime(df$time, tz = "" , format = "%H: %M"), format = "%H: %M")
    df <- data.frame(time)

I suppose I would consider 5-11 the morning, 11-16 the afternoon, 16-19 evening, and anything beyond that and up until 5 night. The original data is in time format as hours:minutes with strptime().

I found some similar problems on the forum but I couldn't seem to tweak the code to work on my data.

标签: r time
5条回答
霸刀☆藐视天下
2楼-- · 2019-05-15 23:24
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"
查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-05-15 23:30

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)))
查看更多
一纸荒年 Trace。
4楼-- · 2019-05-15 23:32

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
查看更多
The star\"
5楼-- · 2019-05-15 23:35

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")))
查看更多
爱情/是我丢掉的垃圾
6楼-- · 2019-05-15 23:36

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

update:

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"
查看更多
登录 后发表回答