基于分组的列筛选标记值偏移处理:避免组重复选中
实现分组唯一选中的R语言方案
需求说明
现有带多分组的有序数据集,selected列是系统按固定间隔标记的选中行(如示例中每4行标记一次),但需遵循核心规则:每个分组只能被选中一次。若系统标记出现同一分组多次选中的情况,需将重复的标记向下偏移,直到找到第一个未被选中过的分组,将该分组的首行标记为选中;其余符合规则的标记保持不变。
示例数据
library(tibble) df <- tibble(group = c(rep("A", 4), rep("B", 2), rep("C", 6), rep("D", 4), rep("E", 2), rep("F", 2)), selected = rep(c(NA, NA, 1, NA), times = 5))
原始数据预览:
# A tibble: 20 x 2 group selected <chr> <dbl> 1 A NA 2 A NA 3 A 1 4 A NA 5 B NA 6 B NA 7 C 1 8 C NA 9 C NA 10 C NA 11 C 1 # 同一分组重复选中,不符合规则 12 C NA 13 D NA 14 D NA 15 D 1 16 D NA 17 E NA 18 E NA 19 F 1 20 F NA
期望结果
# A tibble: 20 x 2 group selected <chr> <dbl> 1 A NA 2 A NA 3 A 1 4 A NA 5 B NA 6 B NA 7 C 1 8 C NA 9 C NA 10 C NA 11 C NA # 重复标记改为NA 12 C NA 13 D NA 14 D NA 15 D 1 16 D NA 17 E 1 # 转移到未被选中的E组首行 18 E NA 19 F 1 20 F NA
实现思路
- 提取候选选中行:先筛选出原始
selected列中值为1的行,记录它们的原始行号和对应分组,形成候选列表。 - 区分合法与重复候选:遍历候选列表,保留每个分组的首次选中标记,将同一分组的后续标记标记为待调整项。
- 收集未被选中的分组:从所有分组中排除已被合法选中的分组,按数据集中的出现顺序生成可用分组列表。
- 调整重复标记位置:对每个待调整的重复标记,按顺序从可用分组列表中取出第一个分组,将该分组的首行设为选中状态,同时移除该分组的可用资格。
- 合并生成最终数据:将合法标记和调整后的标记替换回原始数据,其余行设为NA。
代码实现参考
library(dplyr) library(tibble) # 1. 提取原始候选选中行的行号和分组 original_candidates <- df %>% mutate(row_id = seq_len(nrow(.))) %>% filter(selected == 1) %>% select(row_id, group) # 2. 筛选合法候选(每个分组仅保留第一个选中行) valid_candidates <- original_candidates %>% group_by(group) %>% slice(1) %>% ungroup() # 3. 标记需要调整的重复候选 duplicate_candidates <- original_candidates %>% anti_join(valid_candidates, by = c("row_id", "group")) # 4. 获取按原始顺序排列的未被选中分组 all_groups <- unique(df$group) available_groups <- setdiff(all_groups, valid_candidates$group) # 5. 生成调整后的选中行 adjusted_rows <- integer(0) for (i in seq_len(nrow(duplicate_candidates))) { if (length(available_groups) == 0) break # 取第一个可用分组的首行行号 target_group <- available_groups[1] target_row <- which(df$group == target_group)[1] adjusted_rows <- c(adjusted_rows, target_row) # 移除已使用的分组 available_groups <- available_groups[-1] } # 6. 更新数据集得到最终结果 df_final <- df %>% mutate(row_id = seq_len(nrow(.))) %>% mutate(selected = case_when( row_id %in% valid_candidates$row_id ~ 1, row_id %in% adjusted_rows ~ 1, TRUE ~ NA_real_ )) %>% select(-row_id) # 查看结果 print(df_final)
内容的提问来源于stack exchange,提问作者Rasul89
相关产品推荐
相关产品推荐

