如何为data.table添加列,标记时间是否处于另一表的处理时段内
问题描述
我有一个包含时间点与读数的data.table(dt1),时间间隔可能极不规则;另有一个定义RED、GREEN处理时段的data.table(dt2)。需要为dt1新增TREATMENT列,标记每行时间对应的处理类型,非RED/GREEN时段标记为NULL。尝试用非等连接实现但语法出错,求data.table解决方案。
示例数据
dt1示例:
DATE TIME READING 2022-02-02 11:50:23 123.34 2022-02-02 11:50:59 125.66 2022-02-02 11:51:16 159.23 2022-02-02 11:52:34 234.22
dt2示例:
DATE RED_START RED_END GREEN_START GREEN_END 2022-02-02 11:50:30 11:51:12 11:52:12 11:53:17 2022-02-02 11:54:10 11:55:09 11:56:30 11:57:15
期望输出示例:
DATE TIME READING TREATMENT 2022-02-02 11:50:23 123.34 NULL 2022-02-02 11:50:59 125.66 RED 2022-02-02 11:51:16 159.23 NULL 2022-02-02 11:52:34 234.22 GREEN
尝试的错误代码:
dt1[, RED := c("TRUE","FALSE")[ dt2[.SD, on=.(DATE, RED_START<=TIME, RED_END>=TIME), by=.EACHI] ]]
解决方案
推荐两种可行的data.table实现方式,按需选择:
方法一:重塑表结构后匹配
先把dt2的宽表转成每行对应一个处理时段的长表,再用非等连接匹配,逻辑清晰高效:
library(data.table) # 将dt2拆分为长表,整合RED/GREEN时段信息 dt2_long <- melt(dt2, id.vars = "DATE", measure.vars = patterns("_START$", "_END$"), variable.name = "TREATMENT", value.name = c("START", "END")) # 修正处理类型名称(去掉多余后缀) dt2_long[, TREATMENT := gsub("_START", "", TREATMENT)] # 非等连接匹配,为dt1添加工艺类型 dt1[, TREATMENT := dt2_long[.SD, on = .(DATE, START <= TIME, END >= TIME), x.TREATMENT, by = .EACHI]$V1] # 未匹配到的时段设为NULL dt1[is.na(TREATMENT), TREATMENT := NULL]
方法二:直接分别匹配RED和GREEN
如果不想修改原表结构,可以分别判断每行是否落在RED或GREEN时段内:
library(data.table) # 先标记RED时段 dt1[, TREATMENT := dt2[.SD, on = .(DATE, RED_START <= TIME, RED_END >= TIME), .N > 0, by = .EACHI]$V1] dt1[TREATMENT == TRUE, TREATMENT := "RED"] # 再标记GREEN时段,覆盖未匹配的行 dt1[is.na(TREATMENT), TREATMENT := dt2[.SD, on = .(DATE, GREEN_START <= TIME, GREEN_END >= TIME), .N > 0, by = .EACHI]$V1] dt1[TREATMENT == TRUE, TREATMENT := "GREEN"] # 剩余未匹配的设为NULL dt1[is.na(TREATMENT), TREATMENT := NULL]
内容的提问来源于stack exchange,提问作者rw2
相关产品推荐
相关产品推荐

