R语言按年月日分组统计所有连续小时段长度方法
需求说明
- 运行环境已加载依赖包:
dplyr、tidyr、data.table、lubridate、sqldf - 待处理数据框结构参考:

- 统计规则:按年、月、日维度统计所有独立连续小时段的长度;同一日期内存在多段不相连的连续小时时,需返回全部分段时长,不可仅统计当日最大连续时长
- 期望输出字段:
year、month、day、连续小时数 - 现有代码问题:返回结果存在重复值,仅能统计最大连续时长,原代码如下:
consec <- df1 %>% add_count((hour)!= 1, name = 'Count') %>% group_by(year,month,day)
实现方案
dplyr 实现(适配现有管道操作习惯)
核心逻辑是先按时间顺序排序,通过相邻行小时差值识别连续段边界,给每个独立连续段分配唯一ID后分组计数,不会遗漏同日多段连续时长,也不会产生重复值:
library(dplyr) consec_result <- df1 %>% # 按年、月、日、小时升序排列,保证时间顺序正确 arrange(year, month, day, hour) %>% # 先按自然日分组 group_by(year, month, day) %>% mutate( # 识别连续段边界:首行记为新段起点,当前行小时与上一行差值不为1时也是新段起点 is_new_seg = ifelse(row_number() == 1, TRUE, hour - lag(hour) != 1), # 累计新段起点次数,生成每个连续段的唯一ID seg_id = cumsum(is_new_seg) ) %>% # 按自然日+连续段ID分组,统计段时长 group_by(year, month, day, seg_id) %>% summarise( 连续小时数 = n(), .groups = "drop" ) %>% # 移除中间生成的段ID字段,保留要求的4个输出列 select(year, month, day, 连续小时数)
data.table 实现(适合百万行以上大数据量场景,性能更高)
library(data.table) # 转换为data.table格式 setDT(df1) consec_result_dt <- df1[order(year, month, day, hour)][ , .(连续小时数 = .N), # 直接在分组参数里生成连续段ID,省略中间赋值步骤 by = .(year, month, day, seg_id = cumsum(c(TRUE, diff(hour) != 1))) ][, seg_id := NULL][]
注意:如果原始数据中同一个小时存在多条重复记录,需要先按year,month,day,hour去重后再运行上述代码,否则会把重复记录算入连续时长导致统计结果偏大。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

