如何修改dplyr代码实现重复分组下B值增减1并保留原行
问题描述
初始无重复分组的R数据框:
df <- structure(list(A = c('A', 'B', 'C', 'D', 'E', 'F'), B = c(2, 5, 8, 12, 15, 18)), class = "data.frame", row.names = c(NA, -6L))
用这段dplyr代码可以为每个分组的B值生成减1、原值、加1的行(注:原代码里c(-1,1)其实漏了原值,实际运行仅生成减1和加1的行,若要包含原值需改为c(-1,0,1)),当时运行正常:
df %>% group_by(A) %>% complete(B = B + c(-1,1)) %>% arrange(B)
但当分组存在重复(比如A组同时有B值2和5)时:
df <- structure(list(A = c('A', 'A', 'C', 'D', 'E', 'F'), B = c(2, 5, 8, 12, 15, 18)), class = "data.frame", row.names = c(NA, -6L))
原代码就失效了——没法为每个B值单独生成减1、原值、加1的行,只会输出部分结果。需要修改代码实现需求:给重复分组里的每个B值都生成对应的三个行,同时保持组内顺序。
解决方案
原代码失效的核心原因:group_by(A)后,B + c(-1,1)会把组内所有B值和向量循环相加,而不是针对单个B值生成三个值。要解决这个问题,得把每个(A,B)组合当成独立单元处理:
方法1:用rowwise + expand_grid
library(dplyr) library(tidyr) df %>% rowwise(A, B) %>% # 把每一行(每个A+B的组合)单独分组 expand_grid(B = B + c(-1, 0, 1)) %>% # 针对当前B值生成减1、原值、加1 ungroup() %>% # 取消分组 arrange(A, B) # 按组和B值排序,保证组内顺序
方法2:用group_by + group_modify
如果习惯用分组处理的方式,可以用group_modify对每个(A,B)组合做操作:
library(dplyr) df %>% group_by(A, B) %>% # 按A和B的组合分组 group_modify(~ tibble(B = .x$B + c(-1, 0, 1))) %>% # 为每个分组生成三个B值 ungroup() %>% arrange(A, B)
运行效果
以A组的两个B值2和5为例,会生成以下行:
- 1(2-1)、2(原值)、3(2+1)
- 4(5-1)、5(原值)、6(5+1)
其他分组的单个B值也会正常生成对应的三个行,且所有行按A分组、组内按B值升序排列。
内容的提问来源于stack exchange,提问作者Adamm
相关产品推荐
相关产品推荐

