Convert time object to categorical (morning, afternoon, evening, night) variable in R?

后端 未结 5 946
青春惊慌失措
青春惊慌失措 2020-12-19 20:38

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         


        
相关标签:
5条回答
  • 2020-12-19 21:04
    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"
    
    0 讨论(0)
  • 2020-12-19 21:10

    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
    
    0 讨论(0)
  • 2020-12-19 21:11

    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")))
    
    0 讨论(0)
  • 2020-12-19 21:12

    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"
    
    0 讨论(0)
  • 2020-12-19 21:13

    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)))
    
    0 讨论(0)
提交回复
热议问题