基于组内历史值生成新计数变量的dplyr实现问询
用dplyr实现分组计算距离上次X1=1的周期数
我来帮你搞定这个需求!你需要在每个分组内,计算当前行距离上一次X1取值为1的周期数,并且在之前没有出现过1的行填充NA。下面是用dplyr(结合tidyr的fill函数)实现的完整方案:
示例数据
首先先确认我们的输入数据:
data_test <- data.frame( group = rep(1:4, each = 5), time = rep(1:5, n = 4), X1 = c(0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1) )
解决方案代码
library(dplyr) library(tidyr) data_test <- data_test %>% group_by(group) %>% mutate( # 标记X1=1所在的行号,其他行设为NA last_one_pos = ifelse(X1 == 1, row_number(), NA), # 向前填充最近的X1=1的行号,这样每一行都能拿到最近的1的位置 last_one_pos = fill(last_one_pos, .direction = "down"), # 计算当前行到最近的1的周期数:行号差减1 X2 = row_number() - last_one_pos - 1, # 处理NA的情况: # 1. 第一个1出现之前的行(last_one_pos仍为NA) # 2. 第一个1所在的行(当前行号等于last_one_pos) X2 = case_when( is.na(last_one_pos) ~ NA_integer_, row_number() == last_one_pos ~ NA_integer_, TRUE ~ X2 ) ) %>% ungroup()
代码解释
我们一步步拆解逻辑:
- 分组:用
group_by(group)确保所有计算都在每个分组内独立进行。 - 标记1的位置:
last_one_pos变量记录每个X1=1的行号,其他行暂时为NA。 - 填充最近的1的位置:
fill(last_one_pos, .direction = "down")会把每个NA替换成上方最近的非NA值,这样每一行都能知道离它最近的上一个1在哪里。 - 计算周期数:用当前行号减去最近的1的行号,再减1,就得到了中间间隔的周期数(比如当前行是第4行,最近的1在第3行,4-3-1=0,和示例一致)。
- 修正NA值:通过
case_when把两种需要设为NA的情况筛选出来:还没出现过1的行,以及第一个1所在的行。
运行这段代码后,生成的X2就和你提供的示例完全匹配啦!
内容的提问来源于stack exchange,提问作者Tim Welsh
相关产品推荐
相关产品推荐

