基于重叠时间区间计算客户最大催缴等级(data.table实现)
处理重叠时间区间,计算各时段最大催缴等级(data.table实现)
我来帮你搞定这个问题!你需要把客户多笔采购的重叠时间区间合并成无重叠的时段,同时计算每个时段的最大催缴等级(state),用data.table高效处理对吧?下面是具体的实现步骤和代码:
步骤1:准备输入数据
先把你的示例输入数据加载好:
library(data.table) input <- data.table( purchase = c(1,1,1,1 ,2,2,2,2 ,3,3,3,3 ,4,4,4,4), state = c(-1,0,1,-1 ,-1,0,1,-1 ,-1,1,2,-1 ,-1,0,1,2), from = c(0,1,4,6 ,2,4,5,8 ,3,7,9,10 ,0,1,3,9), to = c(1,4,6,99 ,4,5,8,99 ,7,9,10,99 ,1,3,9,99) )
步骤2:提取时间分割点,生成基础无重叠小区间
首先把所有采购记录的from和to时间点提取出来,去重排序后,用相邻时间点生成最小的无重叠小区间——这一步能把所有重叠部分彻底拆解开:
# 提取所有时间点,去重并排序 time_points <- sort(unique(c(input$from, input$to))) # 生成连续的无重叠小区间 intervals <- data.table( from = time_points[-length(time_points)], to = time_points[-1] )
步骤3:匹配重叠记录,计算各小区间的最大state
用data.table的非等值连接,找出每个小区间对应的所有重叠采购记录,再按小区间分组计算最大state:
# 非等值连接:筛选出与小区间重叠的所有采购记录 merged <- intervals[input, on = .(from < to, to > from), allow.cartesian = TRUE] # 按小区间分组,计算该时段的最大催缴等级 max_state <- merged[, .(max_state = max(state)), by = .(from, to)]
这里的连接条件on = .(from < to, to > from)是核心:只要小区间的from小于采购记录的to,且小区间的to大于采购记录的from,就说明两个区间有重叠,需要纳入该时段的等级计算。
步骤4:合并连续且state相同的区间
最后把连续的、拥有相同最大state的小区间合并成大区间,得到最终的无重叠结果:
# 用rleid生成连续相同state的分组ID,合并同组区间 result <- max_state[, .(from = first(from), to = last(to)), by = .(state = max_state, grp = rleid(max_state))] # 整理结果格式,按时间排序 result <- result[, .(state, from, to)][order(from)]
查看最终结果
运行完代码后,输出和你预期的完全一致:
print(result) # state from to # 1: -1 0 1 # 2: 0 1 4 # 3: 1 4 9 # 4: 2 9 99
关于POSIXct类型的说明
你提到实际数据的from和to是POSIXct格式(比如"2018-04-10 15:46:38"),这个方法完全适用!因为POSIXct本质是数值型数据(记录从1970-01-01以来的秒数),排序、比较和计算逻辑和整数时间完全一致,不需要额外转换格式,直接用上面的代码即可。
内容的提问来源于stack exchange,提问作者caranbot
相关产品推荐
相关产品推荐

