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

如何用R统计个体年度唯一服务天数(解决IVS包单日周期问题)

统计个体不重复服务天数(兼容单日/多日周期)

需求说明

需要统计每个个体一年内接触服务的不重复天数,数据集包含重叠/不重叠的服务周期,其中存在起止日期为同一天的单日记录;要求输出带日期变量的数据框(而非向量),方便后续计算总天数。

示例数据

eg_data <- data.frame(
  id = c(1,1,1,  2,2,  3,3,3,3,3,3,  4,4,  5,5,5,5),
  start_dt = c("01/01/2016", "12/02/2016", "03/12/2017",  "02/01/2016", 
               "03/04/2016",  "01/01/2016", "03/05/2016", "05/07/2016", "07/01/2016", 
               "09/04/2016", "10/10/2016",  "01/01/2016", "05/28/2016",  "01/01/2016", 
               "06/05/2016", "08/25/2016", "11/01/2016"),  
  end_dt =   c("12/01/2016", "12/02/2016", "05/15/2017",  "05/15/2016", 
               "12/29/2016",  "03/02/2016", "04/29/2016", "06/29/2016", "08/31/2016", 
               "03/04/2016", "11/29/2016",  "05/31/2016", "08/19/2016",  "06/10/2016", 
               "07/25/2016", "08/25/2016", "12/30/2016"))
eg_data$row_n <- 1:nrow(eg_data)

之前尝试的代码(存在问题)

无法处理单日周期,且未输出带日期的数据框:

ab <- a %>%
  mutate(
    start_dt = as.Date(ActivityStartDate, format = "%m/%d/%Y"),
    end_dt = as.Date(ActivityEndDate, format = "%m/%d/%Y")
  ) %>%
  mutate(
    range = iv(start_dt, end_dt),
    .keep = "unused"
  )

c <-ab %>%
  group_by(ID) %>%
  mutate(group = iv_identify_group(range)) %>%
  group_by(group, .add = TRUE)

解决方案

方法1:展开日期序列(输出带日期的数据框)

适合需要保留每个服务日期的场景,兼容单日/多日周期:

library(dplyr)
library(lubridate)

# 1. 转换日期格式为Date类型
eg_data_clean <- eg_data %>%
  mutate(
    start_dt = mdy(start_dt),  # 自动识别月/日/年格式
    end_dt = mdy(end_dt)
  )

# 2. 展开每个服务周期的所有日期,去重得到唯一天数
service_dates <- eg_data_clean %>%
  rowwise() %>%
  # 生成从start到end的所有日期(含两端)
  mutate(service_date = list(seq(start_dt, end_dt, by = "day"))) %>%
  unnest(service_date) %>%
  select(id, service_date) %>%
  distinct(id, service_date)  # 按个体和日期去重

# 查看结果(每行对应一个个体的一个服务日期)
head(service_dates)

# 3. 统计每个个体的总不重复服务天数
service_days_count <- service_dates %>%
  group_by(id) %>%
  summarise(total_unique_days = n())

print(service_days_count)

方法2:合并区间(高效统计天数,适合大数据集)

无需展开日期,通过合并重叠/相邻区间计算总天数,同时可按需生成日期序列:

library(dplyr)
library(lubridate)

eg_data_clean <- eg_data %>%
  mutate(
    start_dt = mdy(start_dt),
    end_dt = mdy(end_dt)
  )

# 合并个体的所有服务区间,计算总天数
interval_summary <- eg_data_clean %>%
  group_by(id) %>%
  # 创建闭区间对象(包含起止日期)
  mutate(period = interval(start_dt, end_dt)) %>%
  # 合并重叠或相邻的区间
  summarise(merged_periods = reduce(period, union)) %>%
  # 计算总天数:每个区间的天数(time_length返回间隔天数,需+1补全闭区间)
  mutate(total_unique_days = sum(time_length(merged_periods, "day")) + length(merged_periods))

print(interval_summary)

# 若需要生成日期序列,可从合并后的区间提取
interval_to_dates <- function(intervals) {
  map(intervals, ~ seq(int_start(.x), int_end(.x), by = "day")) %>%
    unlist() %>%
    as.Date(origin = "1970-01-01")
}

# 生成每个个体的服务日期序列
service_dates_from_interval <- interval_summary %>%
  rowwise() %>%
  mutate(service_date = list(interval_to_dates(merged_periods))) %>%
  unnest(service_date) %>%
  select(id, service_date)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:55:43