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?
source to share
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
source to share
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.
source to share
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")
}
}))
source to share