You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按站点移除DataFrame中与前置事件时间重叠的行?

需求说明

我手头有个按Site location分组的DataFrame,记录了不同站点在Start date_time到End date_time区间内的事件。需要做的是:同站点下,只要某事件的开始时间早于或等于该站点里已经保留的更早事件的结束时间,就把这行删掉——说白了就是剔除被前置事件时间范围覆盖的记录。

示例数据如下:

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"
  ))
)

拿示例来说,站点A的第2、3行得删掉——它们的开始时间都≤第1行的结束时间;删掉第3行后,第4行的开始时间晚于第1行的结束时间,所以留着。站点B的所有事件时间都不重叠,全部保留。


解决方案1:用dplyr(tidyverse风格)

核心逻辑就是按站点分组,先把事件按开始时间排好序,然后跟踪当前保留事件的最晚结束时间,逐个判断要不要留。

library(dplyr)

filtered_df <- df %>%
  # 按站点分组,再按开始时间升序排,保证事件按发生顺序处理
  group_by(`Site location`) %>%
  arrange(`Start date_time`, .by_group = TRUE) %>%
  # 标记哪些行要保留:第一行必留,后续行的开始时间得大于之前所有保留事件的最晚结束时间
  mutate(
    keep = case_when(
      row_number() == 1 ~ TRUE,
      `Start date_time` > cummax(lag(`End date_time`)) ~ TRUE,
      TRUE ~ FALSE
    )
  ) %>%
  # 过滤出要保留的行,删掉辅助列,取消分组
  filter(keep) %>%
  select(-keep) %>%
  ungroup()

# 查看结果
print(filtered_df)

代码说明

  1. 分组排序:先按站点分组,再按开始时间排序,确保我们是按事件发生的先后顺序来处理的;
  2. 标记保留行:
    • 每组第一行直接留;
    • 后面的行,用cummax(lag(End date_time))拿到之前所有保留事件的最晚结束时间,只要当前行的开始时间比这个时间大,就留;
  3. 清理输出:筛出要保留的行,删掉临时的keep列,取消分组。

解决方案2:用data.table(大数据场景更高效)

如果你的数据量很大,data.table的处理速度会更快,写法如下:

library(data.table)

setDT(df)
filtered_dt <- df[order(`Site location`, `Start date_time`), 
                  .SD[Reduce(function(last_end, i) {
                    # 逐行判断:当前事件开始时间大于上一个保留事件的结束时间,就留并更新最晚结束时间
                    if (.SD[i, `Start date_time`] > last_end) {
                      last_end <<- .SD[i, `End date_time`]
                      TRUE
                    } else FALSE
                  }, seq_len(.N), init = as.POSIXct(NA), accumulate = TRUE)[-1]], 
                  by = `Site location`]

print(filtered_dt)

代码说明

  • 先按站点和开始时间排序;
  • 用Reduce逐行遍历,跟踪当前保留事件的最晚结束时间,只保留符合条件的行;
  • 按站点分组处理,在大数据量下性能比dplyr更优。

验证结果

不管用哪种方法,最终输出的结果里,站点A只会剩下第1、4、5行,站点B的5行全部保留,完全符合需求。

内容的提问来源于stack exchange,提问作者James White

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:29:51