基于dplyr实现含Check类别的数据组复制扩展与分组分配
使用dplyr实现含Check类别的分组扩展需求
需求说明
当数据组的Class列包含"Check"值时,对该组进行扩展:复制组内非"Check"行,并为新生成的行分配独立分组。
原始数据
test <- data.frame(value = 1:9, group = c("A", "A", "B", "B", "B", "B", "B", "C", "C"), Class = c("Text", "Text", "Text", "Check", "Check", "Check", "Text", "Text", "Check"))
期望结果
desired <- data.frame(value = c(1,2,3,4,7,3,5,7,3,6,7,8,9), group = c("A", "A", "B_1", "B_1", "B_1", "B_2", "B_2", "B_2","B_3", "B_3", "B_3", "C", "C"), Class = c("Text", "Text", "Text", "Check","Text", "Text", "Check","Text", "Text", "Check", "Text", "Text", "Check"))
dplyr解决方案
下面是贴合需求的dplyr实现代码,结合tidyr函数完成分组扩展逻辑:
library(dplyr) library(tidyr) test %>% group_by(group) %>% # 标记当前分组是否包含Check行 mutate(has_check = any(Class == "Check")) %>% # 按分组分别处理 group_modify(function(.x, .y) { # 不含Check的分组直接返回原数据 if (!.x$has_check[1]) { return(.x %>% select(-has_check)) } else { # 拆分非Check行和Check行 non_check_rows <- .x %>% filter(Class != "Check") check_rows <- .x %>% filter(Class == "Check") # 为每个Check行,组合对应非Check行+自身,生成独立分组 pmap_dfr(check_rows, function(...) { current_check <- tibble(...) bind_rows(non_check_rows, current_check) %>% mutate(new_group = paste0(.y$group, "_", current_check$value)) }) %>% select(-has_check) } }) %>% # 替换原group列,无新分组的保留原名称 mutate(group = coalesce(new_group, group)) %>% select(-new_group) %>% ungroup()
代码逻辑说明
- 标记需扩展的分组:通过
has_check字段识别需要处理的分组; - 分组差异化处理:
- 不含"Check"的分组直接保留原数据结构;
- 含"Check"的分组拆分出非Check行和所有Check行,将非Check行与每个Check行分别组合,生成以原分组名+Check行value命名的新分组;
- 整合输出:将新生成的分组名替换原group字段,清理临时字段后输出。
原尝试代码的问题分析
你之前的代码通过uncount复制行,但逻辑是统一复制sum(Class == "Check")次,没有实现每个Check行对应一组独立的非Check行+自身的需求,因此无法生成独立的分组标识。上面的解决方案通过pmap_dfr遍历每个Check行,单独组合对应的数据,完美匹配需求。
内容的提问来源于stack exchange,提问作者Jo Lo
相关产品推荐
相关产品推荐

