如何用dplyr按条件拆分行并复制其余列字符串值?
使用dplyr按条件拆分行的解决方案
可以通过dplyr结合tidyr的函数实现需求,全程无需循环,具体代码如下:
library(dplyr) library(tidyr) # 原始数据 df <- tibble( Group_ID = c(1,2,3,4,5,6), statusA = c("NEW", "NEW", "OLD","NEW", "OLD","OLD"), statusB = c("BONUS", NA, "BONUS", NA, NA,"ROLLBACK"), someVar = c("Thanks", "for", "your", "help","!","!") ) # 处理逻辑 df_processed <- df %>% # 标记需要拆分的行(statusB非NA) mutate(split_flag = !is.na(statusB)) %>% # 为拆分行生成2行,非拆分行保留1行 expand(nesting(Group_ID, someVar, statusA, statusB, split_flag), row_id = ifelse(split_flag, 1:2, 1)) %>% # 按行号设置statusA和statusB的值 mutate( statusA = case_when( split_flag & row_id == 1 ~ statusA, split_flag & row_id == 2 ~ NA_character_, TRUE ~ statusA ), statusB = case_when( split_flag & row_id == 1 ~ NA_character_, split_flag & row_id == 2 ~ statusB, TRUE ~ statusB ) ) %>% # 移除辅助列并调整顺序、排序 select(-split_flag, -row_id) %>% select(Group_ID, statusA, statusB, someVar) %>% arrange(Group_ID)
结果验证
运行以下代码可以确认处理后的数据和预期一致:
# 预期数据 desired_df <- tibble( Group_ID = c(1,1,2,3,3,4,5,6,6), statusA = c("NEW",NA,"NEW","OLD",NA,"NEW","OLD","OLD",NA), statusB = c(NA,"BONUS",NA,NA,"BONUS",NA,NA,NA,"ROLLBACK"), someVar = c("Thanks","Thanks", "for", "your","your","help","!","!","!") ) # 对比验证 all.equal(df_processed, desired_df) # 输出:[1] TRUE
逻辑说明
- 标记拆分行:用
split_flag标识statusB非NA的行,这些行需要拆分 - 生成多行结构:通过
expand函数为拆分行生成两行记录,非拆分行保持一行 - 赋值调整:利用
case_when对拆分后的两行分别设置statusA和statusB的值,实现一行保留原statusA、一行保留原statusB的效果 - 整理结果:移除辅助列,调整列顺序并按
Group_ID排序,得到最终目标数据
内容的提问来源于stack exchange,提问作者RKeithL
相关产品推荐
相关产品推荐

