R语言如何按个体分组标记res从1转0的首次0值并统计次数
原代码的核心问题点
- 行序未按时间排序:同个个体的time值乱序时,滞后类运算按物理行顺序取值,完全匹配不到真实的时间先后关系
- 分组时机错误:
res_next_time在全数据层面计算,没有按个体隔离取数,会跨个体抓取相邻行的res值 - 函数适配性问题:直接使用无分组适配的
Lag函数做滞后取值,哪怕前面加了group_by,也无法在个体的独立窗口内计算,跨组取数错误 - 标记逻辑无校验:只要遇到res=0就前置打标,没有校验“当前0值的前序状态必须为1”,会把连续0序列里所有非跳变起点的0都打上标记
- 统计逻辑错配:因为标记值本身不对,按个体sum得到的flag总次数自然不符合预期
修正后的可运行代码
# 加载依赖包 library(Hmisc) library(dplyr) library(tidyr) # 构造原始测试数据 person <- c(1, 1, 1, 2, 3, 3, 3, 3, 3, 3) time <- c(1, 2, 3, 1, 2, 1, 2, 3, 4, 5) res <- c(1, 0, 1, 1, 1, 0, 0, 1, 0, 1) d <- data.frame(person, time, res) result <- d %>% # 按个体、时间升序排序,保证行序和真实时间顺序一致 arrange(person, time) %>% group_by(person) %>% # 核心标记逻辑 mutate( # 标记规则:仅当“上一时刻res=1,当前时刻res=0”时,赋值flag=1 flag = if_else(lag(res) == 1 & res == 0, 1, 0), # 末行取lag得到的NA按业务要求置0 flag = replace_na(flag, 0), # 按个体统计flag=1的总次数 flag_total = sum(flag) ) %>% ungroup() result
运行结果
# A tibble: 10 x 5 person time res flag flag_total <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 1 1 0 1 2 1 2 0 1 1 3 1 3 1 0 1 4 2 1 1 0 0 5 2 2 1 0 0 6 3 1 0 0 1 7 3 2 0 0 1 8 3 3 1 0 1 9 3 4 0 1 1 10 3 5 1 0 1
结果适配说明
- 个体1:1→0的跳变发生在time1到time2,所以time2的flag=1,总标记数1,连续同状态的0不会被重复打标
- 个体2:全程res保持为1,无任何1→0的跳变,所有flag值为0,总标记数0
- 个体3:开头两个连续的res=0,因为前面没有前置的res=1,所以两个点都不打标;后续time3的res=1跳转到time4的res=0,属于有效跳变,所以time4的flag=1,总标记数1
- 所有取滞后值产生的NA均按业务规则置0,不会出现无效标记
内容的提问来源于stack exchange,提问作者ryorlets
相关产品推荐
相关产品推荐

