R语言长表数据多条件索引行并构造管理晋升派生变量的实现方法
R长格式多条件指标构造实现方案
核心思路
所有指标基于按id分组的时序事件计算,核心是先为每个个体定位关键事件的行索引,再通过索引匹配对应的值,无需嵌套复杂循环或多层ifelse判断。
注意:所有组内记录需要先按age升序排列,保证时序逻辑正确。如果需要适配需求中提到的
m12time列名,只需将代码中对应变量名替换即可,计算逻辑完全一致。
关键规则匹配(完全对齐示例输出)
先为每个id定位两个核心锚点:
- 锚点1:组内首次出现
manage1的行位置,记为m1_pos;如果组内没有manage1,所有和一级管理者相关的指标值为NA - 锚点2:
m1_pos之后首次出现manage2的行位置,记为m2_pos;如果不存在m1_pos或m1_pos之后没有manage2,所有和二级管理者相关的指标值为NA
基于锚点的具体计算规则:
m01time:- 当
m1_pos为组内第一行时,值为NA(没有前置任职记录) - 其他情况从
m1_pos往回遍历,直到碰到第一行left记录或者走到组开头,取该段区间第一行的age作为起始年龄,计算m1_pos对应的age - 起始年龄
- 当
m1p:- 当
m1_pos为组内第一行时,值为NA - 其他情况取
m1_pos前一行的stat值
- 当
m02time(即需求中提到的manage1到manage2的间隔):- 当
m2_pos不存在时,值为NA - 其他情况计算
m2_pos对应的age - m1_pos对应的age
- 当
change:- 当
m2_pos不存在时,值为NA - 其他情况检查
m1_pos和m2_pos的开区间(即两个锚点之间的行,不包含锚点本身)是否存在left记录,存在则取1,不存在则取0
- 当
m2p:- 当
m2_pos不存在时,值为NA - 其他情况取
m2_pos前一行的stat值
- 当
实现代码
library(dplyr) # 构建示例数据集 id <- c(65,65,65,65,65,900,900,900,900,900,900,211,211,211,211,211,211,211,45,45,45,45,45,45,45) age <- c(19,22,23,24,25,21,26,31,32,37,38,22,23,25,28,29,31,32,30,31,36,39,42,44,48) stat <- c('intern','reg','manage1','left','reg','manage1','manage2','left','reg', 'reg','left','intern','left','intern','reg','left','reg','manage1','reg','left','intern','manage1','left','reg','manage2') mydf <- data.frame(id,age,stat) # 按分组索引计算目标变量 result <- mydf %>% group_by(id) %>% arrange(age, .by_group = TRUE) %>% # 强制组内按年龄升序,保障时序正确 summarise( # 定位核心锚点位置 m1_pos = which(stat == "manage1")[1], m2_pos = ifelse(!is.na(m1_pos), which(stat == "manage2" & seq_along(stat) > m1_pos)[1], NA), # 计算m01time和m1p m01time = { if(is.na(m1_pos) | m1_pos == 1){ NA_integer_ } else { back_seq <- seq(m1_pos - 1, 1) first_left_in_back <- back_seq[stat[back_seq] == "left"][1] start_pos <- ifelse(is.na(first_left_in_back), 1, first_left_in_back + 1) age[m1_pos] - age[start_pos] } }, m1p = { if(is.na(m1_pos) | m1_pos == 1) NA_character_ else stat[m1_pos -1] }, # 计算m02time、change和m2p m02time = { if(is.na(m2_pos)) NA_integer_ else age[m2_pos] - age[m1_pos] }, change = { if(is.na(m2_pos)){ NA_integer_ } else { mid_pos <- seq(m1_pos + 1, m2_pos -1) ifelse(any(stat[mid_pos] == "left"), 1L, 0L) } }, m2p = { if(is.na(m2_pos)) NA_character_ else stat[m2_pos -1] }, .groups = "drop" )
输出校验
运行代码后得到的结果表和需求给出的参考结果完全一致,可自动过滤冗余任职记录。这种按索引定位的方式,比逐行嵌套lag/lead的判断逻辑更灵活,能直接适配“断点回溯”类的规则场景。
内容的提问来源于stack exchange,提问作者elliezee
相关产品推荐
相关产品推荐

