使用dplyr实现数值由正转负时生成新分组ID的问题
问题解答
1. 为何cumsum()结合ifelse()会全生成NA?
核心原因是dplyr::lag(X, n=1)的第一个返回值是NA。当执行ifelse(X < 0 & lag(X) > 0, 1, 0)时,第一行的条件判断结果为NA——逻辑运算中只要有NA参与,结果必然是NA。而cumsum()的特性是:一旦累加序列中出现NA,后续所有累加结果都会被污染成NA,最终导致tile_x列全为NA。
单独运行ifelse()时,只有第一行是NA,其余行能正常返回0或1;但传入cumsum()后,NA会直接扩散到所有结果。
2. 不依赖ifelse()/cumsum()的简洁实现
根据你标记转折点后所有行为1、之前为0的需求,提供以下几种简洁方案:
方法一:直接定位转折点赋值(无ifelse/cumsum)
先找到“前值>0、当前值<0”的转折点行号,再通过行号判断赋值:
df1 <- df %>% mutate( tile_x = as.integer(row_number() >= which(X < 0 & lag(X) > 0)) )
如果存在多个转折点,该方法会自动标记第一个转折点后的所有行为1,适配你“分组长度可变但模式一致”的要求。
方法二:用replace函数赋值(无ifelse/cumsum)
通过replace直接替换指定行的值,逻辑更直观:
turn_idx <- which(df$X < 0 & lag(df$X) > 0) df1 <- df %>% mutate(tile_x = replace(rep(0, n()), row_number() >= turn_idx, 1))
方法三:分组标识法(仅用cumsum,无ifelse)
若允许使用cumsum,可通过标记分组起始点生成连续分组编号:
df1 <- df %>% mutate( # 标记分组起始:第一行 + 转折点行 group_start = c(TRUE, X[-1] < 0 & X[-n()] > 0), tile_x = cumsum(group_start) - 1 ) %>% select(-group_start)
该方案支持多个转折点生成0、1、2...的连续分组编号,扩展性更强。
内容的提问来源于stack exchange,提问作者L Tyrone
相关产品推荐
相关产品推荐

