Cutting POSIXlt types by hour in R

Suppose I have the following data

plt <- seq(as.POSIXlt("2010-01-01 01:20:30"), as.POSIXlt("2010-12-31 12:00:30"), 
           length.out = 10)
df <- data.frame(plt)

                   plt
1  2010-01-01 01:20:30
2  2010-02-10 13:11:36
3  2010-03-23 02:02:43
4  2010-05-02 13:53:50
5  2010-06-12 01:44:56
6  2010-07-22 13:36:03
7  2010-09-01 01:27:10
8  2010-10-11 13:18:16
9  2010-11-21 00:09:23
10 2010-12-31 12:00:30

      

What I am trying to do is shorten the next date. What I mean is that I want to assign a coefficient A between hours between 00:00:00 - 06:00:00, a coefficient B until 06:00:01 - 12:00:00, with a coefficient before 12:00:01 - 18: 00: 00, coefficient D until 18:00:01 - 24:00:00. Hopefully the factors will be found in a separate column in df

. Anyone have an idea how to do this?

+3


source to share


3 answers


You can use the POSXlt info to extract the hour and then use cut()

to create your groups



df$timeclass <- cut(as.POSIXlt(df$plt)$hour, 
    breaks=c(0,6,12,18,24), 
    labels=c("A","B","C","D"),
    include.lowest=T)
df
#                    plt timeclass
# 1  2010-01-01 01:20:30         A
# 2  2010-02-10 13:11:36         C
# 3  2010-03-23 02:02:43         A
# 4  2010-05-02 13:53:50         C
# 5  2010-06-12 01:44:56         A
# 6  2010-07-22 13:36:03         C
# 7  2010-09-01 01:27:10         A
# 8  2010-10-11 13:18:16         C
# 9  2010-11-21 00:09:23         A
# 10 2010-12-31 12:00:30         B

      

+3


source


Try to run

library(data.table)
setDT(df) # converts df to a data.table

## Broken down into steps
df[, plt_numb := as.numeric(plt)]
df[, groups   := ((plt_numb - 1) %% 86400) %/% 21600]
df[, group_factors := factor(groups, levels=0:3, labels=c("A", "B", "C", "D"))]

      

In one step:



 df[, newCols := 
        factor({((as.numeric(plt) - 1) %% 86400) %/% 21600}
            , levels = 0:3
            , labels = c("A", "B", "C", "D")
     )]

      

Note that * 86400 == 24 hours * 60 minutes * 60 seconds
* 21600 == 6 hours * 60 minutes * 60 seconds
Thus, accepting modulo 86400 only yields a time value; taking a residual division of 21600 groups the values ​​into sets of 3.

+1


source


You can use lubridate

it to make your life easier. There is probably a better way to do this, but I think this is the easiest way to read.

library(lubridate)
df$time_factor <- as.factor(sapply(df$plt, function(x) {
  date_x <- floor_date(x, "day")
  if(x < date_x + hours(6)){ # time is 6am
    return("A")
  }
  if(x < date_x + hours(12)){ # time is midday
    return("B")
  }
  if(x < date_x + hours(18)){ # time is 6pm
    return("C")
  }
  if(x < date_x + hours(24)){
    return("D")
  }
}))

      

+1


source







All Articles