如何基于分组变量创建触发后值保持不变的滞后二元变量
问题:按规则生成滞后变量NewVar
原始数据
ID visit Switch 1 1 0 1 2 1 2 1 1 2 2 0 3 1 NA 3 2 1 3 3 0 3 4 0 4 1 1
生成NewVar的规则
- 仅拥有1条访视记录的ID,
NewVar设为NA - 存在多条访视记录的ID:
- 一旦
Switch出现1,后续所有访视的NewVar均为1 - 若
Switch初始为0且后续全为0或NA,后续NewVar均为0 - 记录本身是
Switch=1的行,或者该行之前未出现过1且存在NA的情况,NewVar设为NA
- 一旦
期望输出结果
ID visit Switch NewVar 1 1 0 NA 1 2 1 NA 2 1 1 NA 2 2 0 1 3 1 NA NA 3 2 1 NA 3 3 0 1 3 4 0 1 4 1 1 NA
现有代码问题
用户尝试了以下代码,但处理访视次数超过2次的ID(如ID=3)时结果错误,ID=3的第4行NewVar被设为0,不符合期望:
dtmults = dt %>% distinct(ID,visits) %>% group_by(ID) %>% filter(n()>1) %>% arrange(ID) dt %>% filter(ID %in% dtmults$ID) %>% arrange(ID, visits) %>% group_by(ID) %>% mutate(var = Switch, var2 = lag(switch), var3 = var2) %>% fill(var3,.direction="down") %>% rename(NewVar = var3)
解决方案代码
library(dplyr) dt %>% arrange(ID, visit) %>% group_by(ID) %>% mutate( # 标记当前ID是否有多条访视记录 has_multiple = n() > 1, # 找到当前ID中第一次出现Switch=1的访视序号,无则返回Inf first_switch_1 = min(visit[Switch == 1], na.rm = TRUE), # 按规则生成NewVar NewVar = case_when( # 单条记录直接设NA !has_multiple ~ NA_real_, # Switch=1的行,或首次出现1之前的NA行,设NA Switch == 1 | (is.na(Switch) & visit < first_switch_1) ~ NA_real_, # 首次出现1之后的所有行,设为1 visit > first_switch_1 ~ 1, # 所有Switch都是0/NA的ID,除首行外设0 all(Switch %in% c(0, NA), na.rm = TRUE) & visit > first(visit) ~ 0, # 其他情况默认NA TRUE ~ NA_real_ ) ) %>% # 清理临时变量 select(-has_multiple, -first_switch_1) %>% ungroup()
代码说明
first_switch_1:定位每个ID中第一次出现Switch=1的访视号,没有的话返回Inf,用于后续判断行是否在首次出现1之后。case_when逻辑:- 优先处理单条记录的NA情况
- 标记
Switch=1本身的行,以及首次出现1之前的NA行为NA - 只要行的访视号大于首次出现1的位置,直接设为1,确保后续所有行保持1,解决了之前
fill方法无法持续填充1的问题 - 最后处理全为0/NA的ID,后续行设0
- 最后移除临时变量,得到符合要求的结果。
内容的提问来源于stack exchange,提问作者Barayjeemqaf
相关产品推荐
相关产品推荐

