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

R语言按分组统计跨多行日期范围覆盖ISO周的采集天数

问题说明

原始数据集结构如下:

group isoweek     begin.date  end.date    days
A     201933      2019-08-04  2019-08-18  7
A     201934      2019-08-18  2019-08-29  7
A     201935      2019-08-18  2019-08-29  4
A     201936      2019-08-29  2019-09-14  7
A     201937      2019-08-29  2019-09-14  6

现有days列统计逻辑存在缺陷:仅计算当前行begin.date至end.date区间内、对应当前行isoweek的采集天数,没有统计同一采集区间跨到相邻ISO周的天数,导致结果偏差。
以isoweek=201935为例,该ISO周实际范围为2019年8月26日至9月1日,可通过ISOweek包验证:

library(ISOweek)
w <- paste("2019-W35", 1:7, sep = "-")
data.frame(weekdate = w, date = ISOweek2date(w))

结合相邻两个采集区间(2019-08-18至2019-08-29、2019-08-29至2019-09-14),201935周实际覆盖7天采集数据,原统计值4天为错误结果。
需求:按group分组(真实数据包含多个分组),汇总每个isoweek内实际发生数据采集的总天数,修正单行统计的误差,期望输出如下:

group isoweek days 
A     201933  7
A     201934  7
A     201935  7
A     201936  7
A     201937  6
实现方案

核心逻辑:先提取每个分组下所有去重后的采集日期区间,展开为单日采集日期并去重(避免区间交界日期重复计数),再给每个日期匹配对应的ISO周,最后按分组+ISO周统计天数即可,完全规避跨区间漏算问题。

library(dplyr)
library(tidyr)
library(lubridate)

# 读取数据后先将日期列转为Date格式,此处替换为实际数据读取逻辑
df <- df %>%
  mutate(
    begin.date = as.Date(begin.date),
    end.date = as.Date(end.date)
  )

# 计算正确的ISO周采集天数
result <- df %>%
  # 按分组提取所有不重复的采集区间
  select(group, begin.date, end.date) %>%
  distinct() %>%
  group_by(group) %>%
  # 将每个采集区间展开为单日日期序列
  reframe(date = pmap(list(begin.date, end.date), ~seq.Date(.x, .y, by = "day")) %>% unlist()) %>%
  # 跨区间重叠的日期去重
  distinct(group, date) %>%
  # 计算每个日期对应的ISO周,格式与原数据保持一致(4位年+2位周数)
  mutate(
    isoweek = as.integer(paste0(isoyear(date), sprintf("%02d", isoweek(date))))
  ) %>%
  # 按分组、ISO周统计实际采集天数
  count(group, isoweek, name = "days")
  • 代码适配多分组场景,无需额外修改即可自动按分组独立统计。
  • 如果日期区间定义为左闭右开(不包含end.date当日),将seq.Date(.x, .y, by = "day")改为seq.Date(.x, .y - 1, by = "day")即可。
  • 运行结果与期望输出完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 08:57:20