рассчитать продолжительность временного интервала при удалении определенных промежутков времени - PullRequest
0 голосов
/ 20 декабря 2018

Предположим, у нас есть интервал, охватывающий несколько дней (интервал "A" на рисунке ниже).

library(lubridate)
int <- interval("2018-01-01 22:00:00", "2018-01-04 10:00:00")

В часах я получаю

as.period(int, unit = "hours")
"60H 0M 0S"

Теперь я хочу вычестьвсе нерабочие часы, здесь 16: 00-08: 00 (выделены серым цветом) в этом интервале, т. е. оставьте только синие части (08: 00-16: 00) и, опять же, рассчитайте оставшиеся часы (см. «B»«на рисунке ниже), что составляет 8 + 8 + 2 = 18 часов.

enter image description here

Один из подходов заключается в создании списка интервалов Iхотите сохранить, который охватывает весь интервал, а затем рассчитать пересечения.(Приведенный ниже код, конечно, может быть настроен программно с использованием функций floor / floor / seq и т. Д.)

int_keep <- list(
  interval("2018-01-01 08:00:00", "2018-01-01 16:00:00"),
  interval("2018-01-02 08:00:00", "2018-01-02 16:00:00"),
  interval("2018-01-03 08:00:00", "2018-01-03 16:00:00"),
  interval("2018-01-04 08:00:00", "2018-01-04 16:00:00"),
  interval("2018-01-05 08:00:00", "2018-01-05 16:00:00")
)

l <- lapply(int_keep, function(x) intersect(x, int))
mns <- sapply(l, as.numeric)    # returns seconds
sum(mns, na.rm = T) / 60 / 60   # sum of intersections in hours
[1] 18

Хотя это работает, мне это кажется крайне неуклюжим.Что может быть менее утомительным способом сделать это?

1 Ответ

0 голосов
/ 20 декабря 2018
df <- data.frame(DateTime=seq.POSIXt(as.POSIXct("2018-01-01 22:00:00"), as.POSIXct("2018-01-04 10:00:00"), by = "1 hour"))
head(df)
#DateTime
#1 2018-01-01 22:00:00
#2 2018-01-01 23:00:00
#3 2018-01-02 00:00:00
#4 2018-01-02 01:00:00
#5 2018-01-02 02:00:00
#6 2018-01-02 03:00:00

#you want the hours worked between A and B
A <-format(strptime("8:00:00", "%H:%M:%S"),"%H:%M:%S")
B <-format(strptime("16:00:00", "%H:%M:%S"),"%H:%M:%S")
#a simple ifelse statement to assign a value of 1 to column "value" if the time is between 8 and 16 or a 0 if it's not: 
df$value<-ifelse((format(df[1],"%H:%M:%S")>A & format(df[1],"%H:%M:%S")<=B),1,0)
 tail(df)
 #DateTime DateTime
 #56 2018-01-04 05:00:00        0
 #57 2018-01-04 06:00:00        0
 #58 2018-01-04 07:00:00        0
 #59 2018-01-04 08:00:00        0
 #60 2018-01-04 09:00:00        1
 #61 2018-01-04 10:00:00        1
#now taking the column sum of the value column will give you the total hours worked: 
TotalHoursWorked<-colSums(df$value)
TotalHoursWorked
#DateTime 
 # 18 
...