R语言按id分组删除cate=Yes且value=1后的观测值
需求
按id分组,删除每个组中首次匹配到cate=Yes 且 value=1之后的所有观测值。
数据示例
创建数据框的代码:
df <- data.frame( id = c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,5,5,6,6,6,6,7,7,7,7,7), cate = c('No','Yes','Yes','No','Yes','No','Yes','Yes','Yes','No','No','No','Yes','Yes','No','No','Yes','Yes','No',NA,'No','Yes','Yes','Yes','No','Yes','Yes','Yes','Yes'), value = c(0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0) )
原始数据输出:
id cate value 1 1 No 0 2 1 Yes 0 3 1 Yes 0 4 1 No 0 5 1 Yes 0 6 2 No 0 7 2 Yes 1 8 2 Yes 0 9 2 Yes 0 10 2 No 0 11 3 No 0 12 3 No 0 13 3 Yes 0 14 3 Yes 0 15 3 No 0 16 4 No 0 17 4 Yes 0 18 4 Yes 0 19 5 No 0 20 5 Yes 0 21 6 No 0 22 6 Yes 1 23 6 Yes 0 24 6 Yes 0 25 7 No 0 26 7 Yes 1 27 7 Yes 1 28 7 Yes 0 29 7 Yes 0
预期输出
id cate value 1 1 No 0 2 1 Yes 0 3 1 Yes 0 4 1 No 0 5 1 Yes 0 6 2 No 0 7 2 Yes 1 8 3 No 0 9 3 No 0 10 3 Yes 0 11 3 Yes 0 12 3 No 0 13 4 No 0 14 4 Yes 0 15 4 Yes 0 16 5 No 0 17 5 Yes 0 18 6 No 0 19 6 Yes 1 20 7 No 0 21 7 Yes 1
解决方案
方法1:dplyr实现(推荐)
通过分组标记首次匹配位置,保留该位置及之前的行:
library(dplyr) result_df <- df %>% group_by(id) %>% mutate( # 标记目标行 target = (cate == "Yes" & value == 1), # 取首次匹配的行号,无匹配则取组内行数+1,保留所有行 first_target_pos = min(which(target), n() + 1) ) %>% filter(row_number() <= first_target_pos) %>% select(-target, -first_target_pos) %>% ungroup() print(result_df)
方法2:base R实现
拆分分组后逐个处理,再合并结果:
# 按id拆分数据框 grouped_list <- split(df, df$id) # 逐个处理每个分组 processed_list <- lapply(grouped_list, function(group) { target_rows <- which(group$cate == "Yes" & group$value == 1) if (length(target_rows) > 0) { # 保留到首次匹配的行 group[1:target_rows[1], ] } else { # 无匹配则保留全部 group } }) # 合并分组结果并重置行名 result_df <- do.call(rbind, processed_list) rownames(result_df) <- NULL print(result_df)
内容的提问来源于stack exchange,提问作者Mahlet Tadesse
相关产品推荐
相关产品推荐

