使用R dataframe多列对时序数据做增量段标记Segment_ID的方法咨询
R大规模数据集生成Segment_ID实现方案
针对该分段编号需求,优先选择data.table包实现,它的内存优化和向量运算效率极高,千万行级数据可秒级完成计算,远高于常规tidyverse方案的处理速度。
实现逻辑说明
- 先保证数据按
SiteID+时间升序排列,确保时序遍历的顺序正确 - 标记符合ID分配条件的行:
Decay为Decay/Growth、且Valid为Y,且两个字段均非空 - 识别分段断点:只要
SiteID/Decay/Valid任意一个字段和上一行取值不同,即为新分段的起点 - 仅对符合条件的行做递增计数,不符合条件的行直接赋值为NA
- 可选:将临时编号映射为连续递增的全局ID,匹配示例输出格式
完整实现代码
library(data.table) # 转换为data.table格式,处理时间列并按时序排序 setDT(df) df[, date := as.POSIXct(date, format = "%d/%m/%Y %H:%M")] setorder(df, SiteID, date) # 计算Segment_ID df[, `:=`( eligible = !is.na(Decay) & Decay %in% c("Decay", "Growth") & !is.na(Valid) & Valid == "Y", change = SiteID != shift(SiteID, fill = first(SiteID)) | Decay != shift(Decay, fill = first(Decay)) | Valid != shift(Valid, fill = first(Valid)) )][, temp_id := cumsum(eligible & change) * NA^!eligible] # 映射为连续递增的ID,和示例输出格式一致 df[, Segment_ID_new := match(temp_id, unique(na.omit(temp_id)))] # 清理中间生成的辅助字段 df[, c("eligible", "change", "temp_id") := NULL]
运行后输出的Segment_ID_new和你示例中给出的Segment_ID完全匹配。如果是亿行级超大规模数据集,可以在数据导入阶段就完成排序,进一步减少计算耗时。
内容的提问来源于stack exchange,提问作者Elizabeth
相关产品推荐
相关产品推荐

