R语言使用data.table按ticker分组筛选非重叠日期区间事件的方案求解
原代码问题分析
- 没有按
ticker分组计算偏移,全局调用shift会将不同ticker的行做对比,直接导致大量合法行被误删。 - 偏移的
fill参数设置错误,你给shift(Event_start, type="lead")填充逻辑值T(等价于数值1)、给shift(Event_end, type="lag")填充逻辑值F(等价于数值0),日期和逻辑值对比会触发隐式类型转换,计算逻辑完全失效。 - 仅依赖相邻行的重叠判断逻辑存在漏洞,如果出现跨多行的非相邻重叠(比如第一行和第三行重叠但和第二行不重叠),该逻辑无法正确识别,最终结果必然不符合预期。
正确实现方案
这个需求属于典型的分组去区间重叠场景,用data.table的分组+累计最大值逻辑即可高效实现,8万行数据运行无压力,不会出现内存不足问题:
library(data.table) # 转换为data.table格式 setDT(final_arrange) # 按ticker分组,每组内按开始日期排序后过滤无重叠事件 result <- final_arrange[order(ticker, Event_start), .SD[Event_start > shift(cummax(Event_end), fill = as.Date(-Inf))], by = ticker]
逻辑说明
- 先按
ticker分组,每组内按Event_start升序排列,保证按时间先后顺序处理事件 cummax(Event_end)计算到当前行为止所有事件的最大结束日期shift(..., fill = as.Date(-Inf))将累计最大结束日期上移一行,代表所有已保留事件的最大结束时间- 只要当前事件的开始日期大于已保留事件的最大结束日期,说明和之前所有事件都无重叠,直接保留即可
如果你的业务规则中区间端点相等算重叠,将上述代码中的>改为>=即可。
过往报错说明
你使用grepl时出现的长度错误,是因为grepl第一个参数要求传入单个正则匹配模式,你传入了整个ticker列,程序只会取第一个元素做匹配,自然不符合需求。该场景不需要用grepl做匹配,data.table的by参数已经实现了按ticker分组的逻辑。
内容的提问来源于stack exchange,提问作者TribokThorsten
相关产品推荐
相关产品推荐

