在R中按条件分组交换行值:将value=1的行与下一行value互换
解决方案
原数据
company_name <- c("A","A","A","A","B","B","B") year <- c(1985, 1986, 1987, 1988, 1985, 1986, 1987) value <- c(0, 1, 0, 0, 1, 0, 0) df <- data.frame(company_name, year, value)
需求说明
按company_name分组,当某行的value为1时,将该行与下一行(下一行value为0)的value值交换,最终得到如下结果:
value <- c(0, 0, 1, 0, 0, 1, 0) new_df <- data.frame(company_name, year, value)
实现代码(使用dplyr)
library(dplyr) new_df <- df %>% group_by(company_name) %>% mutate( # 标记需要交换的行:当前行value=1且下一行value=0 swap_flag = value == 1 & lead(value, default = -1) == 0, # 执行交换逻辑 value = case_when( swap_flag ~ lead(value), lag(swap_flag, default = FALSE) ~ lag(value), TRUE ~ value ) ) %>% select(-swap_flag) %>% ungroup() # 查看结果 print(new_df)
逻辑解释
- 分组处理:通过
group_by(company_name)确保交换操作仅在同一家公司的行内进行,不会跨公司干扰。 - 标记交换行:用
swap_flag标记满足条件的行——当前行value为1,且下一行的value为0(lead(value, default = -1)避免最后一行因无后续行出现误判)。 - 执行交换:
- 被标记的
swap_flag行,直接取后一行的value; - 被标记行的下一行(通过
lag(swap_flag)判断),取上一行的value; - 其他行保留原
value不变。
- 被标记的
- 清理输出:移除临时标记列
swap_flag,取消分组得到最终数据框。
结果验证
运行代码后,new_df的value列将完全符合预期:c(0, 0, 1, 0, 0, 1, 0)。
内容的提问来源于stack exchange,提问作者Yusuf
相关产品推荐
相关产品推荐

