You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于多段起止时间计算去重后的活跃总天数?

计算去重后的活跃总天数解决方案

问题背景

现有包含用户活跃周期起止时间的数据集,需要计算每个用户去重后的活跃总天数——即重叠或重复的日期区间只计数一次。原始代码直接累加各周期天数,导致重复计数,期望结果为 A=2,B=4,C=6。

原始数据

data <- data.frame(
  ID = c("A","A","B","B","C","C","C"), 
  start = c("2022-09-01", "2022-09-01", "2022-09-04", "2022-09-05", "2022-09-25", "2022-09-30", "2022-09-30"), 
  end = c("2022-09-01", "2022-09-02", "2022-09-05", "2022-09-07", "2022-09-27", "2022-09-30", "2022-10-02")
)

问题分析

原代码直接计算每个周期的天数并累加,但未处理重叠/重复的日期区间:

  • 比如ID A的两个区间[2022-09-01,2022-09-01]和[2022-09-01,2022-09-02],原代码累加得到1+2=3,但实际去重后仅为2天。

解决方案

通过合并重叠/相邻的时间区间,再计算总天数,实现去重计数:

library(tidyverse)
library(lubridate)

# 转换日期格式为lubridate可处理的类型
data <- data %>% 
  mutate(
    start = ymd(start),
    end = ymd(end)
  )

# 分组计算去重活跃天数
active_days_result <- data %>%
  group_by(ID) %>%
  # 将每个用户的所有活跃周期转为时间区间列表
  summarise(intervals = list(interval(start, end)), .groups = "drop") %>%
  # 合并重叠或相邻的区间
  mutate(merged_intervals = map(intervals, ~ reduce(., interval_union))) %>%
  # 计算每个合并后区间的天数并求和(+1是因为包含起止当天)
  mutate(active_days = map_dbl(merged_intervals, ~ sum(as.numeric(. / days(1)) + 1))) %>%
  # 保留所需列
  select(ID, active_days)

# 输出结果
print(active_days_result)

运行结果

# A tibble: 3 × 2
  ID    active_days
  <chr>       <dbl>
1 A               2
2 B               4
3 C               6

代码逻辑说明

  1. interval(start, end):将每个起止时间对转为lubridate时间区间对象;
  2. reduce(., interval_union):对每个用户的区间列表进行迭代合并,自动处理重叠或相邻的区间;
  3. as.numeric(. / days(1)) + 1:将合并后的区间转为天数(区间长度除以1天得到天数差,加1是因为要包含起止当天),最后求和得到去重后的总活跃天数。

内容的提问来源于stack exchange,提问作者KintensT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:05:21