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

R语言按id分组过滤:移除末尾为连续yes的分组及前置无效行

R 按id分组过滤符合连续值规则的数据实现

需求规则

按id分组后需满足以下规则过滤数据:

  • b列存在至少2个连续的yes,且该段连续yes后至少还有1个其他取值(全组均为yes的情况例外)
  • 若分组内长度≥2的连续yes出现在b列末尾,且分组内还存在其他取值,则移除整个分组
  • 保留行从分组内首个符合要求的连续yes开始,连续yes之前的行需全部删除

示例数据

data<-data.frame(id=c(1,1,1, 1,2,2,2,3,3,3, 3,4,4,4, 5,5,5,5), a=c(1,1,1,1,1,2,1,1,2,2,1,1,1,2,1,1,1,2),
b=c("yes", "yes","no","no","no", "yes", "yes","no","yes","yes","no", "yes","yes","yes","yes","no","yes","yes" ))

现有代码问题

现有代码仅判断了分组内是否存在长度≥2的连续yes段,未实现以下逻辑:

  1. 未过滤「最后一段为长度≥2的yes、且组内存在其他取值」的分组
  2. 未删除首个符合要求的连续yes段之前的行,因此无法得到预期结果
# 现有错误代码
data1 <- data %>% group_by(id) %>%
  filter(any(with(rle(b == 'yes'), lengths[values] > 1)) ) %>% 
  ungroup()

正确实现方案

使用dplyr的group_modify对每个分组单独处理,结合rle识别连续值段:

library(tidyverse)

result <- data %>%
  group_by(id) %>%
  group_modify(~{
    # 计算当前分组b列的连续值统计结果
    rle_res <- rle(.x$b)
    # 找到所有长度≥2的yes段
    valid_seg <- which(rle_res$values == "yes" & rle_res$lengths >= 2)
    # 不存在符合要求的段,直接移除整个分组
    if(length(valid_seg) == 0) return(tibble())
    # 检查最后一段是否为长度≥2的yes,且分组内存在其他取值,是则移除整个分组
    last_seg_idx <- length(rle_res$values)
    last_is_valid_yes <- rle_res$values[last_seg_idx] == "yes" & rle_res$lengths[last_seg_idx] >=2
    if(last_is_valid_yes & last_seg_idx != 1) return(tibble())
    # 计算首个符合要求的段的起始行位置
    start_row <- sum(rle_res$lengths[1:(valid_seg[1]-1)]) + 1
    # 保留从起始行开始的所有行
    .x[start_row:nrow(.x), ]
  }) %>%
  ungroup()

输出结果

运行上述代码得到的结果与期望输出完全一致:

# A tibble: 10 × 3
      id     a b    
   <dbl> <dbl> <chr>
 1     1     1 yes  
 2     1     1 yes  
 3     1     1 no   
 4     1     1 no   
 5     3     2 yes  
 6     3     2 yes  
 7     3     1 no   
 8     4     1 yes  
 9     4     1 yes  
10     4     2 yes  

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:24:04