r - 如何按时间间隔连接 2 个数据表并按因子变量汇总重叠和非重叠时间段
问题描述
我有 2 个数据表,每个表都列出了观察努力的时期和努力的类型(A、B、C)。我想知道重叠和不重叠的努力期的持续时间。
我尝试使用 data.table 和 foverlaps 来做到这一点,但无法弄清楚如何包含所有非重叠时段。
这是我的示例数据。我首先创建了 2 个包含工作时间的数据表。我的数据集将包括单个观察者正在努力的时间段。
library(data.table)
library(lubridate)
# times have been edited so not fixed to minute intervals - to make more realistic
set.seed(13)
EffortType = sample(c("A","B","C"), 100, replace = TRUE)
On = sample(seq(as.POSIXct('2016/01/01 01:00:00'), as.POSIXct('2016/01/03 01:00:00'), by = "1 sec"), 100, replace=F)
Off = On + minutes(sample(1:60, 100, replace=T))
Effort1 = data.table(EffortType, On, Off)
EffortType2 = sample(c("A","B","C"), 100, replace = TRUE)
On2 = sample(seq(as.POSIXct('2016/01/01 12:00:00'), as.POSIXct('2016/01/03 12:00:00'), by = "1 sec"), 100, replace=F)
Off2 = On2 + minutes(sample(1:60, 100, replace=T))
Effort2 = data.table(EffortType2, On2, Off2)
#prep for using foverlaps
setkey(Effort1, On, Off)
setkey(Effort2, On2, Off2)
然后我使用 foverlaps 来查找工作重叠的位置。我设置了 nomatch=NA,但这只是给了我正确的外部连接。我想要完整的外部连接。所以我想知道更合适的功能是什么。
matches = foverlaps(Effort1,Effort2,type="any",nomatch=NA)
我继续在这里展示我如何尝试确定所有重叠和非重叠轮班时间的持续时间。但我不认为我有这部分是正确的。
# find start and end of intersection of all shifts
matches$start = pmax(matches$On, matches$On2, na.rm=T)
matches$end = pmin(matches$Off, matches$Off2, na.rm=T)
# create intervals and find durations
matches$int = interval(matches$start, matches$end)
matches$dur = as.duration(matches$int)
然后我想总结每个“EffortType”分组的观察努力时间
最后得到这样的结果(数字只是示例,因为我还没有设法弄清楚如何正确计算它,即使在 excel 中也是如此)
EffortType Duration(in minutes)
A 10
B 20
C 12
AA 8
BB 6
CC 1
AC 160
AB 200
BC 150
解决方案
不是整个答案(见最后一段)..但我认为这会让你得到你想要的。
library( data.table )
library( lubridate )
set.seed(13)
EffortType = sample(c("A","B","C"), 100, replace = TRUE)
On = sample(seq(as.POSIXct('2016/01/01 01:00:00'), as.POSIXct('2016/01/03 01:00:00'), by = "15 mins"), 100, replace=T)
Off = On + minutes(sample(1:60, 100, replace=T))
Effort1 = data.table(EffortType, On, Off)
EffortType2 = sample(c("A","B","C"), 100, replace = TRUE)
On = sample(seq(as.POSIXct('2016/01/01 12:00:00'), as.POSIXct('2016/01/03 12:00:00'), by = "15 mins"), 100, replace=T)
Off = On + minutes(sample(1:60, 100, replace=T))
Effort2 = data.table(EffortType2, On, Off)
#create DT of minutes, spanning your entire period.
dt.minutes <- data.table( On = seq(as.POSIXct('2016/01/01 01:00:00'), as.POSIXct('2016/01/03 12:00:00'), by = "1 mins"),
Off = seq(as.POSIXct('2016/01/01 01:00:00'), as.POSIXct('2016/01/03 12:00:00'), by = "1 mins") + 60 )
#prep for using foverlaps
setkey(Effort1, On, Off)
setkey(Effort2, On, Off)
#overlap join both efforts on the dt.minutes. note the use of "within" an "nomatch" to throw away minutes without events.
m1 <- foverlaps(dt.minutes, Effort1 ,type="within",nomatch=0L)
m2 <- foverlaps(dt.minutes, Effort2 ,type="within",nomatch=0L)
#bind together
result <- rbindlist(list(m1,m2))[, `:=`(On=i.On, Off = i.Off)][, `:=`(i.On = NULL, i.Off = NULL)]
#cast the result
result.cast <- dcast( result, On + Off ~ EffortType, value.var = "EffortType")
结果是
head( result.cast, 10)
# On Off A B C
# 1: 2016-01-01 01:00:00 2016-01-01 01:01:00 1 0 1
# 2: 2016-01-01 01:01:00 2016-01-01 01:02:00 1 0 1
# 3: 2016-01-01 01:02:00 2016-01-01 01:03:00 1 0 1
# 4: 2016-01-01 01:03:00 2016-01-01 01:04:00 1 0 1
# 5: 2016-01-01 01:04:00 2016-01-01 01:05:00 1 0 1
# 6: 2016-01-01 01:05:00 2016-01-01 01:06:00 1 0 1
# 7: 2016-01-01 01:06:00 2016-01-01 01:07:00 1 0 1
# 8: 2016-01-01 01:07:00 2016-01-01 01:08:00 1 0 1
# 9: 2016-01-01 01:08:00 2016-01-01 01:09:00 1 0 1
# 10: 2016-01-01 01:09:00 2016-01-01 01:10:00 1 0 1
有时一个事件在同一分钟内发生 2-3 次,例如
# On Off A B C
#53: 2016-01-02 14:36:00 2016-01-02 14:37:00 2 2 3
不知道你想如何总结...
如果您可以将它们视为一分钟,那么:
> sum( result.cast[A>0 & B==0, C==0, ] )
[1] 476
> sum( result.cast[A==0 & B>0, C==0, ] )
[1] 386
> sum( result.cast[A==0 & B==0, C>0, ] )
[1] 504
> sum( result.cast[A>0 & B>0, C==0, ] )
[1] 371
> sum( result.cast[A==0 & B>0, C>0, ] )
[1] 341
> sum( result.cast[A>0 & B==0, C>0, ] )
[1] 472
> sum( result.cast[A>0 & B>0, C>0, ] )
[1] 265
我认为可以在几分钟内获得持续时间(尽管这可能会以更聪明的方式完成)
推荐阅读
- c# - MySQL:从 C# 批量发送 20000 SELECT 查询
- java - WebClient builder Post Call 在 Webflux 中首次给出错误请求错误
- angular - 如何在剑道日期选择器中将过去日期显示为禁用日期
- r - R ggplot - 使用“stat_compare_mean”时每个面板的不同 y 轴
- python - 合并两个熊猫数据框,其中一个是另一个的子集(或仅填充列的子集)
- json - 首次启动颤振时保存和检索 json 对象
- c# - 尝试将列表转换为数组会产生“错误 CS1503:参数 1:无法从 'System.Collections.Generic.List 转换
' 到 'System.Array' " - uwp - 如何在 uwp 中删除文本块的填充?
- javascript - 当按钮从 Web 浏览器控件按下到 WPF 时生成事件
- angular - 如何在 Angular 应用程序中使用 powerbi-client 依赖项,而不破坏笑话测试?