我有一个带有分组 ID(“站点位置”)的数据框,其中“开始日期时间”和“结束日期时间”之间发生了不同的事件。我想弄清楚如何删除事件的开始日期时间早于或等于该站点位置发生的较早事件的结束日期时间的行。或者换句话说,如何删除数据框中较高位置已发生的事件(具有相同的“站点位置”)。
一些示例数据:
df <- data.frame("Site location" = rep(c("A","B"),each = 5),
"Start date_time" = as.POSIXct(c("2022-01-01 00:00","2022-01-01 00:45","2022-01-01 01:00","2022-01-01 03:00","2022-01-01 04:00",
"2022-01-01 00:00","2022-01-01 01:00","2022-01-01 02:00","2022-01-01 03:00","2022-01-01 04:00")),
"End date_time" = as.POSIXct(c("2022-01-01 01:00","2022-01-01 01:15","2022-01-01 03:00","2022-01-01 03:15","2022-01-01 05:00",
"2022-01-01 00:45","2022-01-01 01:45","2022-01-01 02:45","2022-01-01 03:45","2022-01-01 04:45")))
所以在这个例子中,我想删除第2行和第3行,因为它们的开始日期/时间早于或等于第1行的结束日期/时间。删除第3行意味着应保留第4行in(如果第 3 行未被删除,我希望将其过滤为第 4 行的开始日期 == 第 3 行的结束日期)。所有其他行都可以保留,因为没有其他交叉。
提前非常感谢。
解决方案如下:
(1) 确保数据按站点开始时间排序
(2) 使用
shift()
查看前一行的结束时间(站点组内)
并将前面的结束时间与当前行的开始/结束时间进行比较,如果时间重叠为真则分配一个虚拟变量
(3) 找到第一个 TRUE 重叠的
Position
,如果第一个索引等于当前行的索引(在站点组内),则添加另一个虚拟变量“is_simultaneous”
(4) 重复删除观察结果为“is_simultaneous”的任何第一个索引实例,直到没有留下为止。
library(data.table)
setDT(df)
setorder(df,
Site.location,
Start.date_time,
End.date_time)
df[,site_rank:=.I,
by=.(Site.location)]
repeat {
df[,
time_overlaps:= shift(End.date_time,
n=1,
fill=NA,
type="lag") %between% list(Start.date_time,End.date_time),
by=.(Site.location)]
df[,
is_simultaneous:=Position(f=isTRUE,
time_overlaps,
nomatch=0)==.I,
by=.(Site.location)]
if (!any(df$is_simultaneous)) {
break;
} else {
df <- df[is_simultaneous==FALSE]
}
}
清理虚拟变量
df[,
`:=`(time_overlaps=NULL,
is_simultaneous=NULL)]
结果显示site_rank第2行和第3行已被删除