問題
目前,我有一個大型機組人員時間表資料集,其中包含開始和結束時間,我的目標是確定員工是否在夜班作業。夜班定義為 01:00:00 到 05:59:59 之間的任何班次。我查看了諸如 %overlaps% 之類的函式,但這些似乎不適用于時間戳。一些示例資料(以 UTC-tz 為單位):
library(lubridate)
df <- data.frame(start = ymd_hms(c("2018-09-19 23:30:00", "2018-09-19 17:00:00", "2018-09-22 04:30:00")),
end = ymd_hms(c('2018-09-20 07:05:00', "2018-09-19 21:00:00", "2018-09-22 12:00:00")))
解決方案
理想情況下,我想獲得以下輸出,其中一個布爾變數指示員工是否上夜班:
start end night.shift
2018-09-19 23:30:00 | 2018-09-20 07:05:00 | TRUE
2018-09-19 17:00:00 | 2018-09-19 21:00:00 | FALSE
2018-09-22 04:30:00 | 2018-09-22 12:00:00 | TRUE
提前致謝!
uj5u.com熱心網友回復:
使用seq.POSIXt
transform(df, night.shift=mapply(\(x, y) any(
as.POSIXct(outer(as.Date(c(x, y)), c('01:00:00', '05:59:59'), paste), tz='GMT') %in%
seq.POSIXt(x, y, by='sec')),
start, end))
# start end night.shift
# 1 2018-09-19 23:30:00 2018-09-20 07:05:00 TRUE
# 2 2018-09-19 17:00:00 2018-09-19 21:00:00 FALSE
# 3 2018-09-22 04:30:00 2018-09-22 12:00:00 TRUE
%inrange%或者,幾乎是data.table包裝速度的兩倍。
library(data.table)
transform(df, night.shift=mapply(\(x, y) any(
as.POSIXct(outer(as.Date(c(x, y)), c('01:00:00', '05:59:59'), paste), tz='GMT') %inrange%
c(x, y)),
start, end))
# start end night.shift
# 1 2018-09-19 23:30:00 2018-09-20 07:05:00 TRUE
# 2 2018-09-19 17:00:00 2018-09-19 21:00:00 FALSE
# 3 2018-09-22 04:30:00 2018-09-22 12:00:00 TRUE
uj5u.com熱心網友回復:
您可以使用interval()或%--%創建一個Interval物件并int_overlaps()測驗兩個間隔是否重疊。
library(dplyr)
library(lubridate)
df %>%
mutate(
night.shift = int_overlaps(
(date(start) hms("01:00:00")) %--% (date(start) hms("05:59:59")),
start %--% end
) | int_overlaps(
(date(end) hms("01:00:00")) %--% (date(end) hms("05:59:59")),
start %--% end
)
)
另一種方法是使用%within%來檢查日期時間物件是否在一個區間內。
df %>%
rowwise() %>%
mutate(
night.shift = any(outer(date(c(start, end)), hms(c("01:00:00", "05:59:59")), ` `) %within% (start %--% end))
) %>%
ungroup()
輸出
# # A tibble: 4 × 3
# start end night.shift
# <dttm> <dttm> <lgl>
# 1 2018-09-19 23:30:00 2018-09-20 07:05:00 TRUE
# 2 2018-09-19 17:00:00 2018-09-19 21:00:00 FALSE
# 3 2018-09-22 04:30:00 2018-09-22 12:00:00 TRUE
# 4 2018-09-22 04:30:00 2018-09-23 00:30:00 TRUE
參考
用于創建和操作 Interval 物件的實用程式
uj5u.com熱心網友回復:
這是超級janky 并且沒有優化,但它可以作業(并且很有趣)。如果可能,您將希望對其進行矢量化。
library(lubridate)
df <- data.frame(start = ymd_hms(c("2018-09-19 23:30:00", "2018-09-19 17:00:00", "2018-09-22 04:30:00")),
end = ymd_hms(c('2018-09-20 07:05:00', "2018-09-19 21:00:00", "2018-09-22 12:00:00")))
night <- interval( hms::as_hms(3600), hms::as_hms(21599), tz = "UTC")
print(night)
for(i in 1:3) {
s = df$start[i]
f = df$end[i]
start_seconds = hms::as_hms(60*60*hour(s) 60*minute(s) second(s))
end_seconds = hms::as_hms(60*60*hour(f) 60*minute(f) second(f))
interval <- interval(start_seconds, end_seconds, tz = "UTC")
t <- int_overlaps(night, interval)
print(t)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/468950.html
下一篇:如何檢查程式cout是否為空?
