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

在R/SQL中按Key分组处理行:基于duration与Cond的合并或日期更新

嘿,我来帮你搞定这个分组内的行合并和时间调整需求!先理清楚逻辑,再给你写可运行的R代码~

解决方案:分组内逐行合并与时间调整

首先,我们需要先把原始数据中的日期列转换成日期类型,方便后续的日期运算。然后针对每个key分组,逐行判断下一行的duration是否小于其对应的Cond,来决定是合并行还是调整下一行的起始日期。

步骤说明

  1. 数据预处理:将Start和End列从字符型转换为日期类型,同时确保duration和Cond是数值型,避免运算错误。
  2. 分组处理逻辑:
    • 对每个key组内的行按id排序(保证行的顺序符合需求中的“第N行/第N+1行”关系)。
    • 遍历组内每一行:
      • 如果下一行的duration < Cond:将当前行与下一行合并,更新当前行的End为下一行的End,直接跳过下一行。
      • 如果下一行的duration >= Cond:保留当前行,将下一行的Start设置为当前行End的次日,然后保留这两行。
  3. 结果整合:将每个组处理后的结果合并成最终的数据框。

完整代码

# 加载所需工具包
library(dplyr)
library(lubridate)

# 你的原始数据
df <- as.data.frame(cbind(key = c(30, 30, 40, 40, 50, 50, 50, 60, 60, 60, 70, 70, 70, 80, 80, 80, 90, 90, 90, 90), 
                          id = c(1, 2, 1, 2, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 4), 
                          value = c("A", "B", "C", "D", "A", "C", "D", "B", "C", "D", "A", "C", "D","A", "C", "D", "A", "B", "C", "D"), 
                          Class = c("A,B", "B", "C,D", "D", "A,C,D", "C,D", "D", "B,C,D", "C,D", "D", "A,C,D", "C,D", "D", "A,C,D", "C,D", "D", "A,B,C,D", "B,C,D", "C,D", "D"), 
                          duration = c(NA, 19, NA, 168, NA, 16, 28, NA, 49, 47, NA, 60, 17, NA, 2, 2, NA, 21, 23, 299), 
                          Cond = c(NA, 20, NA, 30, NA, 30, 20, NA, 20, 30, NA, 5, 28, NA, 20, 30, NA, 30, 20, 28), 
                          Start = c("2018-02-27", "2018-02-27", "2018-12-17", "2018-12-17", "2018-04-10", "2018-04-10", "2018-04-10", "2016-05-13", "2016-05-13", "2016-05-13", "2017-01-09", "2017-01-09", "2017-01-09", "2020-09-08", "2019-09-18", "2019-09-18", "2017-01-17", "2017-01-17", "2017-01-17", "2017-01-17"), 
                          End = c("2018-03-07", "2018-03-26", "2018-12-25", "2019-06-11", "2018-06-21", "2018-07-07", "2018-08-04", "2016-05-18", "2016-07-06", "2016-08-22", "2017-11-01", "2017-12-31", "2018-01-17", "2020-01-07", "2020-01-09", "2020-01-11", "2017-02-15", "2017-03-08", "2017-03-31", "2018-01-24") ))

# 预处理:转换日期列和数值列类型
df <- df %>%
  mutate(Start = ymd(Start),
         End = ymd(End),
         duration = as.numeric(duration),
         Cond = as.numeric(Cond))

# 定义处理单个分组的函数
process_group <- function(group_df) {
  result <- list()
  i <- 1
  n <- nrow(group_df)
  
  while(i <= n) {
    current_row <- group_df[i, ]
    
    if(i < n) {
      next_row <- group_df[i+1, ]
      
      # 跳过duration为NA的情况,只判断有数值的行
      if(!is.na(next_row$duration) && next_row$duration < next_row$Cond) {
        # 合并行:更新当前行的End为下一行的End
        current_row$End <- next_row$End
        result[[length(result)+1]] <- current_row
        i <- i + 2 # 跳过下一行,避免重复处理
      } else {
        # 保留当前行,调整下一行的Start为当前行End的次日
        result[[length(result)+1]] <- current_row
        next_row$Start <- current_row$End + days(1)
        result[[length(result)+1]] <- next_row
        i <- i + 2
      }
    } else {
      # 最后一行直接加入结果
      result[[length(result)+1]] <- current_row
      i <- i + 1
    }
  }
  
  bind_rows(result)
}

# 应用分组处理逻辑
processed_df <- df %>%
  arrange(key, id) %>%
  group_by(key) %>%
  group_modify(~ process_group(.x)) %>%
  ungroup()

# 查看处理后的完整结果
print(processed_df, n = nrow(processed_df))

结果说明

  • 对于key=30的组:id=2的duration(19) < Cond(20),所以合并两行,最终只有一行,End更新为2018-03-26。
  • 对于key=40的组:id=2的duration(168) >= Cond(30),所以保留两行,id=2的Start调整为2018-12-26(原id=1的End+1天)。
  • 多id的组(比如key=90)会逐行依次判断处理,完全符合你的需求规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:57:56