R语言:按日期和小时统计ID工作频次(含短时长取整)
解决方案
步骤说明
要实现按日期+小时统计ID工作频次,并对不足5分钟的时长取整,可按以下流程处理:
- 将每条登录登出记录拆分为其覆盖的所有小时区间
- 计算每个小时区间内的实际工作时长
- 过滤或取整不足5分钟的无效时长
- 按日期和小时分组统计活跃ID的频次
R代码实现
# 加载依赖包 library(tidyverse) library(lubridate) # 导入数据集 df <- structure(list(ID = c(1, 2, 2, 3, 4, 5, 6, 6, 7), Start = structure(c(1682980601.9993, 1682976528.9996, 1682981213.9999, 1682976550, 1682977034.9995, 1682976647.9992, 1682974125.9996, 1682976497.9993, 1682979153.9993), class = c("POSIXct", "POSIXt"), tzone = "UTC"), End = structure(c(1683009115.9995, 1682980675.9992, 1683010288.9996, 1683010949.9993, 1683008750.9992, 1683007497, 1682976313.9993, 1683008357.9993, 1683008503.9998), class = c("POSIXct", "POSIXt"), tzone = "UTC")), row.names = c(NA, -9L), class = c("tbl_df", "tbl", "data.frame")) # 数据处理与统计 hourly_stats <- df %>% # 生成每条记录覆盖的所有小时区间 mutate(hour_seq = map2(Start, End, ~seq(floor_date(.x, "hour"), ceiling_date(.y, "hour"), by = "hour"))) %>% unnest(hour_seq) %>% # 计算当前小时内的实际工作时长(分钟) mutate( interval_start = pmax(Start, hour_seq), interval_end = pmin(End, hour_seq + hours(1)), duration_min = as.duration(interval_end - interval_start) / dminutes(1), # 过滤不足5分钟的无效时长 is_valid = duration_min >= 5 ) %>% filter(is_valid) %>% # 按日期、小时分组统计活跃ID频次 mutate( 统计日期 = date(hour_seq), 统计小时 = hour(hour_seq) ) %>% group_by(统计日期, 统计小时) %>% summarise( 活跃ID数量 = n_distinct(ID), 总有效时长_分钟 = sum(duration_min) %>% round(1) ) %>% ungroup() # 查看结果 print(hourly_stats)
代码说明
- 小时区间拆分:通过
floor_date和ceiling_date锁定每条记录覆盖的首尾整点小时,生成完整的小时序列 - 时长计算:取登录时间与小时区间的较晚值作为区间起点,登出时间与小时区间的较早值作为区间终点,计算实际停留时长
- 无效时长过滤:直接过滤时长不足5分钟的记录,确保统计的是有效活跃的ID
- 频次统计:按日期和小时分组,用
n_distinct(ID)统计该时段内的活跃ID数量,同时可计算总有效时长作为补充指标
自定义取整规则
如果需要将时长按5分钟单位取整(而非直接过滤),可替换is_valid部分的代码:
# 向下取整到最近的5分钟倍数 duration_rounded = floor(duration_min / 5) * 5 # 向上取整到最近的5分钟倍数 duration_rounded = ceiling(duration_min / 5) * 5 # 四舍五入到最近的5分钟倍数 duration_rounded = round(duration_min / 5) * 5
内容的提问来源于stack exchange,提问作者Mo S
相关产品推荐
相关产品推荐

