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

如何修正状态时间线数据:优先保留a、b,消除c的时间重叠

解决状态时长重叠问题:调整C状态适配A/B优先级

嘿,我刚好能帮你搞定这个状态重叠修正的需求——毕竟A、B优先级高于C,只能动C的起止时间,甚至如果A/B把C的时间全占了就直接删掉C记录对吧?我给你写了一套基于R的实现方案,完美匹配你给出的示例数据场景。

首先先把你的示例数据加载进来

# 加载示例数据
df <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L), 
                     period = c("a", "b", "c", "a", "b", "c", "a", "a", "b", "c", "a", "b"), 
                     start = c(3L, 11L, 8L, 18L, 20L, 26L, 31L, 1L, 11L, 13L, 15L, 16L), 
                     end = c(10L, 12L, 20L, 19L, 25L, 32L, 35L, 10L, 14L, 17L, 15L, 20L)), 
                class = "data.frame", row.names = c(NA, -12L))

核心实现思路

我这套方案的逻辑很清晰:

  • 按个体(id)分组,先把每个个体下的A、B状态区间提取出来(题目说A/B本身无重叠,所以直接用就行)
  • 对每个C状态的区间,计算它和A/B区间的非重叠部分,只保留这些有效片段;如果C的区间被A/B完全覆盖,就直接删掉这条C记录
  • 最后把原有的A/B记录和修正后的C记录合并,按时间排序得到最终结果

完整代码实现

我用了dplyr和purrr来简化分组和循环处理,代码可读性很高:

library(dplyr)
library(purrr)

# 定义工具函数:计算单个C区间与A/B区间的非重叠有效部分
get_valid_c_intervals <- function(c_start, c_end, exclude_intervals) {
  # 先把A/B区间整理成有序的不重叠区间(即使题目说A/B无重叠,这步也能让代码更鲁棒)
  exclude_intervals <- exclude_intervals %>%
    arrange(start) %>%
    mutate(
      group = cumsum(ifelse(start > lag(end, default = -Inf), 1, 0))
    ) %>%
    group_by(group) %>%
    summarise(start = min(start), end = max(end)) %>%
    ungroup() %>%
    select(start, end)
  
  current_start <- c_start
  valid_segments <- list()
  
  # 逐个检查A/B区间,切割C区间
  for (i in 1:nrow(exclude_intervals)) {
    ex_start <- exclude_intervals$start[i]
    ex_end <- exclude_intervals$end[i]
    
    # 如果当前C区间的起点在A/B区间之前,这段就是有效部分
    if (current_start < ex_start) {
      valid_segments <- append(valid_segments, list(data.frame(start = current_start, end = ex_start - 1)))
    }
    
    # 更新C区间的起点到A/B区间的终点之后
    current_start <- max(current_start, ex_end + 1)
    if (current_start > c_end) break
  }
  
  # 检查循环结束后是否还有剩余的有效C区间
  if (current_start <= c_end) {
    valid_segments <- append(valid_segments, list(data.frame(start = current_start, end = c_end)))
  }
  
  # 返回有效区间,没有的话返回空数据框
  if (length(valid_segments) == 0) {
    data.frame(start = numeric(0), end = numeric(0))
  } else {
    bind_rows(valid_segments)
  }
}

# 主流程处理数据
result <- df %>%
  group_by(id) %>%
  group_split() %>%
  map_dfr(function(group_df) {
    # 分离A/B记录和C记录
    ab_df <- group_df %>% filter(period %in% c("a", "b"))
    c_df <- group_df %>% filter(period == "c")
    
    # 处理每个C记录
    processed_c <- if (nrow(c_df) > 0) {
      c_df %>%
        rowwise() %>%
        mutate(valid = list(get_valid_c_intervals(start, end, ab_df))) %>%
        unnest(valid) %>%
        select(id, period, start, end) %>%
        filter(start <= end) # 过滤掉无效的空区间
    } else {
      data.frame(id = integer(0), period = character(0), start = integer(0), end = integer(0))
    }
    
    # 合并A/B和处理后的C记录,按时间排序
    bind_rows(ab_df, processed_c) %>%
      arrange(start)
  })

# 查看最终结果
print(result)

效果验证

  • 对于id=1的个体:
    原C区间8-20会被A(3-10)、B(11-12)、A(18-19)切割,变成两段有效区间:13-17和20-20;原C区间26-32会被A(31-35)切割,变成26-30。
  • 对于id=2的个体:
    A/B的区间(1-10、11-14、15-15、16-20)完全覆盖了C的13-17区间,所以处理后没有C记录,完全符合你的期望。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:48:36