在data.table中查找连续点事件间存在的其他类型事件
解决连续点事件间的线事件匹配问题
需求说明
我们有两类带时间属性的事件:
- 点事件(
pt类型):仅包含单个时间点(start列) - 线事件(
line类型):包含起始和结束时间(start和stop列)
需要按subject分组,对每一对连续的点事件,判断它们的时间区间内(或与该区间重叠)是否存在对应的线事件。比如示例中,点B(19)和C(22)之间没有线事件,其余点对均存在匹配的线事件。
实现步骤
以下是基于data.table的高效解决方案:
- 拆分数据集:将点事件和线事件分开处理,同时按
subject分组
library(data.table) # 拆分点事件和线事件 dt_pt <- dt1[type == "pt", .(subject, pt_id = id, pt_time = start)] dt_line <- dt1[type == "line", .(subject, line_start = start, line_stop = stop)]
- 生成连续点对的时间区间:对每个subject的点事件按时间排序,生成前一个点和当前点的区间
# 按subject分组,对时间排序,生成连续点对 dt_pt[, `:=`(prev_pt_time = shift(pt_time), prev_pt_id = shift(pt_id)), by = subject] # 过滤掉没有前序点的行(每个subject的第一个点) dt_pairs <- dt_pt[!is.na(prev_pt_time), .(subject, prev_pt = prev_pt_id, curr_pt = pt_id, pair_start = prev_pt_time, pair_stop = pt_time)]
- 匹配点对区间与线事件:用
foverlaps判断每个点对区间是否和同subject的线事件存在重叠
# 设置foverlaps需要的键 setkey(dt_line, subject, line_start, line_stop) setkey(dt_pairs, subject, pair_start, pair_stop) # 执行重叠匹配,保留匹配到的记录 matches <- foverlaps(dt_pairs, dt_line, type = "any", nomatch = NULL) # 标记每个点对是否存在匹配的线事件 dt_pairs[, has_line_event := FALSE] dt_pairs[matches[, .(subject, prev_pt, curr_pt)], has_line_event := TRUE, on = .(subject, prev_pt, curr_pt)]
- 查看最终结果
print(dt_pairs)
运行后输出结果(符合示例预期):
subject prev_pt curr_pt pair_start pair_stop has_line_event 1: subjA A B 16 19 TRUE 2: subjA B C 19 22 FALSE 3: subjA C D 22 27 TRUE 4: subjA D E 27 29 TRUE 5: subjA E F 29 32 TRUE
关键说明
foverlaps的type = "any"参数会匹配所有与点对区间有重叠的线事件,包括线事件完全包含点对区间、点对区间包含线事件、部分重叠的情况- 按
subject分组确保我们只匹配同一主体内的事件,避免跨主体的错误匹配 - 最终的
has_line_event列清晰标记了每个连续点对是否存在对应的线事件
内容的提问来源于stack exchange,提问作者Vasily A
相关产品推荐
相关产品推荐

