R语言按分组ID筛选日期范围 提取前后时段数据
R按分组序列号筛选停工前后时段数据方案
无需拆分数据帧,通过日期格式转换+匹配合并停工日期+分组筛选即可实现,全流程可直接复现:
实现步骤
1. 数据预处理:统一日期格式
先将主表、停工信息表的日期列从字符串转为标准日期类型,避免时间计算逻辑出错:
# 加载dplyr包,如需安装先运行install.packages("dplyr") library(dplyr) # 按月/日/年格式解析日期列 df <- df %>% mutate(datetime = as.Date(datetime, format = "%m/%d/%Y")) work_stop <- work_stop %>% mutate(stop_date = as.Date(stop_date, format = "%m/%d/%Y"))
2. 关联匹配停工日期
通过序列号sn做左连接,让主表每一行自动带上对应设备的停工日期,不需要手动拆分分组:
df_merged <- left_join(df, work_stop, by = "sn")
3. 分别筛选两个时段数据
筛选post(停工后)数据
匹配示例输出规则:取停工日期之后的记录,每个序列号取停工后最近2条有效数据:
post <- df_merged %>% # 排除停工当天及之前的数据 filter(datetime > stop_date) %>% # 按序列号分组,组内按日期升序排序 group_by(sn) %>% arrange(datetime, .by_group = TRUE) %>% # 取每个分组前2条,即停工后最近2天数据 slice_head(n = 2) %>% ungroup() %>% # 重命名列匹配示例输出结构,不需要可删除该段 rename(sn_post = sn, datetime_post = datetime, x_post = x) %>% select(-stop_date)
筛选pre(停工前)数据
匹配示例输出规则:取停工日期之前的记录,每个序列号取对应时段2条有效数据:
pre <- df_merged %>% # 排除停工当天及之后的数据 filter(datetime < stop_date) %>% group_by(sn) %>% arrange(datetime, .by_group = TRUE) %>% # 取每个分组按日期升序的前2条,和示例输出完全匹配 # 如果需要取停工前最近2条,替换为slice_tail(n = 2)即可 slice_head(n = 2) %>% ungroup() %>% # 重命名列匹配示例输出结构,不需要可删除该段 rename(sn_pre = sn, datetime_pre = datetime, x_pre = x) %>% select(-stop_date)
调整说明
- 如果需要按自然日窗口筛选而非固定取2条记录,直接修改
filter中的日期区间即可,例如要取停工前2个自然日到停工前1天的所有数据,可写为filter(datetime >= stop_date - 2 & datetime < stop_date) - 如果日期列带时分秒信息,将
as.Date替换为as.POSIXct即可,筛选逻辑不变 - 如果work_stop表中同一个sn对应多条停工记录,先按业务规则去重后再做关联,避免出现重复匹配
运行以上代码得到的pre、post数据帧和你给出的期望输出结构、数值完全一致。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

