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

如何在R中统计满足条件的连续有效工作日天数及次数

问题需求

给定包含itinerary(行程)、service(服务提供商)、date(日期)、flag(布尔标记)的数据集,需完成:

  1. 筛选出存在至少3个连续有效工作日(周五与周一视为连续)且flag=1的行程
  2. 统计这类连续有效工作日区间的出现次数

最小可用数据集

# 生成连续日期并剔除周末
days <- rep(seq(as.Date('2024-03-01'), as.Date('2024-03-14'), '1 day'), 1, each = 10)
days <- days[!weekdays(days) %in% c('Saturday','Sunday')]

# 创建最小工作数据集
set.seed(1337)
df <- tibble(
  itinerary = rep(101:110, 10),
  service = rep(c("CIA", "CIA", "FBI", "FBI", "FBI", "FBI", "NSA", "NSA", "CIA", "FBI"), 10),
  date = days,
  flag = sample(c(0,1), 100, replace = TRUE))

# 查看数据集前6行
> head(df)
# A tibble: 6 × 4
  itinerary service date        flag
      <int> <chr>   <date>     <dbl>
1       101 CIA     2024-03-01     1
2       102 CIA     2024-03-01     0
3       103 FBI     2024-03-01     1
4       104 FBI     2024-03-01     0
5       105 FBI     2024-03-01     1
6       106 FBI     2024-03-01     1

已尝试方案

方案1:基于日期差值分组(存在缺陷)

该方案通过日期差值判断连续性,但无法识别周五与周一的连续关系:

df_working <- df %>% 
  group_by(itinerary, service, flag) %>% 
  mutate(grp = cumsum(c(TRUE, diff(date) != 1))) %>% 
  group_by(grp, .add = TRUE) %>% 
  summarise(
    len = n(),
    start_date = first(date),
    end_date = last(date),
    .groups = 'drop'
  )

# 查看结果前6行
> head(df_working)
# A tibble: 6 × 7
  itinerary service  flag   grp   len start_date end_date  
      <int> <chr>   <dbl> <int> <int> <date>     <date>    
1       101 CIA         0     1     1 2024-03-05 2024-03-05
2       101 CIA         0     2     1 2024-03-08 2024-03-08
3       101 CIA         0     3     2 2024-03-11 2024-03-12
4       101 CIA         1     1     1 2024-03-01 2024-03-01
5       101 CIA         1     2     1 2024-03-04 2024-03-04
6       101 CIA         1     3     2 2024-03-06 2024-03-07

方案2:基于有效日期序列分组(可行但冗余)

通过构建有效工作日的连续序列解决了周五-周一连续问题,但代码较为繁琐:

# 提取数据中所有唯一有效日期并生成连续序号
days_unique <- unique(days) %>% as_tibble() %>% 
  arrange() %>% rename(date = value) %>% mutate(seq = row_number())

# 关联序号后分组计算连续天数
df_test <- df %>% 
  left_join(days_unique, join_by(date)) %>% 
  group_by(itinerary, service, flag) %>% 
  mutate(grp = cumsum(c(TRUE, diff(seq)) != 1)) %>% 
  group_by(grp, .add = TRUE) %>% 
  mutate(cons_days = ifelse(seq == first(seq), last(seq) - seq +1, 0)) %>% 
  summarise(
    cons_days = max(cons_days),
    start_date = first(date),
    end_date = last(date),
    .groups = 'drop'
  )

# 查看结果前6行
> head(df_test)
# A tibble: 6 × 7
  itinerary service  flag   grp cons_days start_date end_date  
      <int> <chr>   <dbl> <int>     <dbl> <date>     <date>    
1       101 CIA         0     0         1 2024-03-05 2024-03-05
2       101 CIA         0     1         3 2024-03-08 2024-03-12
3       101 CIA         1     0         2 2024-03-01 2024-03-04
4       101 CIA         1     1         2 2024-03-06 2024-03-07
5       101 CIA         1     2         2 2024-03-13 2024-03-14
6       102 CIA         0     0         2 2024-03-01 2024-03-04

优化后的简洁稳健方案

直接基于有效工作日逻辑生成连续分组,无需额外关联序号表:

library(dplyr)
library(lubridate)

# 1. 筛选flag=1数据减少计算量,按行程、服务、日期排序
# 2. 生成有效工作日连续分组:周五到周一视为连续
result <- df %>%
  filter(flag == 1) %>%
  arrange(itinerary, service, date) %>%
  group_by(itinerary, service) %>%
  mutate(
    # 修正周五到周一的日期差值,将其视为连续工作日
    workday_diff = as.integer(date - lag(date)) - 
      case_when(
        wday(lag(date)) == 5 & wday(date) == 2 ~ 2, # 周五到周一实际间隔3天,减去2天转为连续标记
        TRUE ~ 0
      ),
    grp = cumsum(c(TRUE, workday_diff != 1))
  ) %>%
  # 按分组统计连续天数、起止日期
  group_by(itinerary, service, grp, .add = FALSE) %>%
  summarise(
    consecutive_days = n(),
    start_date = first(date),
    end_date = last(date),
    .groups = "drop"
  ) %>%
  # 筛选连续天数≥3的记录
  filter(consecutive_days >= 3)

# 统计每个行程的连续情况次数
summary_result <- result %>%
  group_by(itinerary) %>%
  summarise(
    total_consecutive_periods = n(),
    .groups = "drop"
  )

结果查看

查看符合条件的连续工作日区间:

> head(result)

查看各行程的连续情况统计:

> summary_result

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:52:46