如何基于正数转对应负数的偏移对DataFrame序列分组?
基于正负值偏移规则的序列分组实现方法
问题描述
现有如下名为df的DataFrame:
value 1 -4 2 -3 3 -2 4 -1 5 0 6 1 7 2 8 3 9 -3 10 -2 11 -1 12 0 13 1 14 2 15 3 16 -3 17 -2 18 -1 19 0 20 1 21 2 22 -2 23 -1 24 0 25 1 26 2 27 3 28 4
需要基于正数变为其对应的负数的偏移规则对value列进行分组:当某行的正数等于下一行值的相反数时(即当前行值x>0,下一行值为-x),则该行及之前的所有行归为一组。例如第8行值为3,第9行值为-3,那么第1至8行属于一组;第15行值为3,第16行值为-3,同样触发分组,以此类推。
期望输出如下:
value group 1 -4 1 2 -3 1 3 -2 1 4 -1 1 5 0 1 6 1 1 7 2 1 8 3 1 9 -3 2 10 -2 2 11 -1 2 12 0 2 13 1 2 14 2 2 15 3 2 16 -3 3 17 -2 3 18 -1 3 19 0 3 20 1 3 21 2 3 22 -2 4 23 -1 4 24 0 4 25 1 4 26 2 4 27 3 4 28 4 4
df的dput代码:
df <- structure(list(value = c(-4, -3, -2, -1, 0, 1, 2, 3, -3, -2, -1, 0, 1, 2, 3, -3, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, 3, 4)), class = "data.frame", row.names = c(NA, -28L))
解决方案
可以通过以下步骤实现分组:
- 识别触发分组的边界行:判断当前行的
value是否为正数,且等于下一行value的相反数。 - 根据边界生成分组标识:对边界进行累加,从而得到每行对应的分组编号。
具体R代码如下:
library(dplyr) df <- df %>% # 标记触发分组的行(当前行满足条件时,下一行属于新组) mutate(is_group_boundary = value > 0 & lead(value) == -value) %>% # 填充最后一行的边界标记(默认不触发) replace_na(list(is_group_boundary = FALSE)) %>% # 累加边界标记,生成分组编号(初始为1,每遇到一个边界加1) mutate(group = cumsum(is_group_boundary) + 1) %>% # 移除中间辅助列 select(-is_group_boundary)
代码解释
is_group_boundary = value > 0 & lead(value) == -value:创建一个布尔列,标记当前行是否是分组的结束行(即下一行要进入新组)。lead(value)用于获取下一行的value值。replace_na(list(is_group_boundary = FALSE)):因为最后一行没有下一行,所以将其边界标记设为FALSE,避免NA值影响累加。group = cumsum(is_group_boundary) + 1:对边界标记进行累加,每遇到一个TRUE(即一个分组结束),累加值加1,再加上初始的1,得到分组编号。
执行上述代码后,即可得到符合要求的分组结果。
内容的提问来源于stack exchange,提问作者Quinten
相关产品推荐
相关产品推荐

