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

如何在R语言中筛选事件前后行子集并处理重叠事件

筛选事件前后行并处理重叠与完整性问题

需求说明

给定包含参与者id、事件标记event(1表示事件发生)、关注变量x的数据框,需要:

  • 提取每个event对应的前后2行(含事件本身)共5行的数据
  • 处理两个问题:部分事件的筛选行存在重叠,首尾事件的行集不完整
  • 优先实现:移除重叠事件,仅保留无重叠的完整行集(优先保留先发生的事件);若无法实现则保留所有行,优先给先发生的事件标记cum_id,后续重叠事件保留不完整行

示例数据

df <- structure(list(id = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), event = c(1L, 
0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 
1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 
0L), x = c(-0.524745604197535, 0.56664753932467, 1.06326937193775, 
-1.74261927944691, -1.70220588525303, 0.788056468394497, -0.315524780669081, 
-1.09956621127396, 0.725332798657826, -0.821455118910762, -0.305075137324048, 
0.0975277444454113, -1.37607536240115, -1.1749745326815, -0.0254452552627888, 
0.0291714672416614, -0.560221734093268, -0.832517971223058, 1.01067311827293, 
-0.0101155699102594, -2.211772959964, -0.324879965548731, 0.189774016276101, 
-0.124110438315279, 0.87450859784393, 0.534102255268043, 0.483572995043595, 
0.717566852172195, 0.62058456685663, 0.100291898582953, -1.97147667641014, 
0.390331677978558, -2.44481260988607, -1.08221493718706, 1.282044558805, 
1.46339582810391, -0.388529539761603, -1.0347479743086, -0.244983560420757, 
-0.745529649917578, -0.581202927866314, -0.0468146194831979, 
0.353756786882484, 0.726051987010529, 0.785563528600549, 0.234591665330184, 
0.661859569057452, 0.718155884148953, 1.02606212190121, 0.35208377496606
)), row.names = c(NA, -50L), class = "data.frame")

方案一:移除重叠事件,保留无重叠的完整行集

实现思路

  1. 为数据添加行号,定位每个事件的位置
  2. 计算每个事件的行范围(事件行号±2),并标记是否为完整的5行集(即范围不超出当前参与者的行边界)
  3. 按参与者分组,优先保留先发生的、无重叠的完整事件
  4. 提取对应行并添加cum_id

代码实现

library(dplyr)
library(purrr)

# 添加行号
df <- df %>% mutate(row_num = row_number())

# 提取事件的行范围及完整性标记
event_ranges <- df %>%
  filter(event == 1) %>%
  group_by(id) %>%
  mutate(
    start = row_num - 2,
    end = row_num + 2,
    is_complete = start >= min(row_num) & end <= max(row_num)
  ) %>%
  ungroup()

# 筛选无重叠的完整事件
selected_events <- event_ranges %>%
  group_by(id) %>%
  arrange(row_num) %>%
  mutate(
    # 检查当前事件与已保留事件是否重叠
    overlap = map_lgl(row_number(), function(i) {
      if (i == 1) return(FALSE)
      any((start <= lag(end, n = i-1)) & (end >= lag(start, n = i-1)))
    })
  ) %>%
  filter(is_complete & !overlap) %>%
  ungroup()

# 提取最终结果并添加cum_id
result1 <- df %>%
  inner_join(selected_events %>% select(id, start, end), by = "id") %>%
  filter(row_num >= start & row_num <= end) %>%
  group_by(id) %>%
  mutate(cum_id = cumsum(event == 1)) %>%
  ungroup() %>%
  select(id, cum_id, event, x)

# 查看结果
print(result1)

方案二:保留所有行,优先标记先发生事件

实现思路

  1. 为数据添加行号,标记每个事件的cum_id
  2. 按事件发生顺序,为每个事件的行范围分配cum_id,重叠行优先归属到先发生的事件
  3. 保留所有行,最终按参与者和行号排序

代码实现

library(dplyr)
library(data.table)

# 转换为data.table方便批量处理
setDT(df)
df[, row_num := .I]

# 标记每个事件的cum_id
events <- df[event == 1, .(id, event_row = row_num, cum_id = seq_len(.N)), by = id]

# 为行分配cum_id,优先覆盖未标记的行
df[, cum_id := NA_integer_]
for (i in seq(nrow(events))) {
  id_i <- events$id[i]
  start <- events$event_row[i] - 2
  end <- events$event_row[i] + 2
  df[id == id_i & row_num >= start & row_num <= end & is.na(cum_id), cum_id := events$cum_id[i]]
}

# 整理结果并排序
result2 <- df[order(id, row_num), .(id, cum_id, event, x)]

# 查看结果
print(result2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:15:55