在R语言中提取个体状态转移年龄对并构建转移表格
问题描述
原始数据集
| PTNUM | STATE | AGE | WAVE |
|---|---|---|---|
| 12345 | 1 | 17 | 1 |
| 12345 | 1 | 20 | 2 |
| 12345 | 2 | 26 | 3 |
| 12345 | 3 | 31 | 4 |
| 12345 | 2 | 37 | 5 |
| 12346 | 1 | 15 | 1 |
| 12346 | 1 | 23 | 2 |
| 12346 | 1 | 28 | 3 |
| 12346 | 1 | 33 | 4 |
| 12346 | 1 | 41 | 5 |
| 12347 | 1 | 19 | 1 |
| 12347 | 2 | 23 | 2 |
| 12347 | 2 | 29 | 3 |
| 12347 | 3 | 32 | 4 |
| 12347 | 3 | 39 | 5 |
| 12348 | 1 | 17 | 1 |
| 12348 | 2 | 22 | 2 |
| 12348 | 3 | 29 | 3 |
| 12348 | 2 | 31 | 4 |
| 12348 | 3 | 40 | 5 |
| 12349 | 1 | 12 | 1 |
| 12349 | 2 | 19 | 2 |
| 12349 | 2 | 24 | 3 |
| 12349 | 2 | 30 | 4 |
| 12349 | 3 | 36 | 5 |
需求说明
需要为每个个体(按PTNUM分组)提取三种状态转移对应的年龄对,规则如下:
- 1→2转移:取该个体最后一次处于STATE 1的AGE,以及首次进入STATE 2的AGE,组合为
(age1, age2);若未发生该转移则填NA。 - 2→3转移:取该个体最后一次处于STATE 2的AGE(在首次进入STATE 3之前的最后一次),以及首次进入STATE 3的AGE,组合为
(age2, age3);若未发生该转移则填NA。 - 3→2转移:取该个体首次转回STATE 2之前最后一次处于STATE 3的AGE,以及此次转回STATE 2的AGE,组合为
(age3, age2);若未发生该转移则填NA。
预期输出
| PTNUM | 1-2 | 2-3 | 3-2 |
|---|---|---|---|
| 12345 | (20,26) | (26,31) | (31,37) |
| 12346 | NA | NA | NA |
| 12347 | (19,23) | (29,32) | NA |
| 12348 | (17,22) | (22,29) | (29,31) |
| 12349 | (12,19) | (30,36) | NA |
请问如何在R语言中实现这一需求?
R语言实现方案
使用dplyr包进行分组处理,结合位置筛选和汇总逻辑即可实现需求,以下是完整可运行代码:
# 加载依赖包 library(dplyr) # 构造原始数据集 df <- tibble( PTNUM = c(12345,12345,12345,12345,12345, 12346,12346,12346,12346,12346, 12347,12347,12347,12347,12347, 12348,12348,12348,12348,12348, 12349,12349,12349,12349,12349), STATE = c(1,1,2,3,2, 1,1,1,1,1, 1,2,2,3,3, 1,2,3,2,3, 1,2,2,2,3), AGE = c(17,20,26,31,37, 15,23,28,33,41, 19,23,29,32,39, 17,22,29,31,40, 12,19,24,30,36), WAVE = c(1,2,3,4,5, 1,2,3,4,5, 1,2,3,4,5, 1,2,3,4,5, 1,2,3,4,5) ) # 分组计算转移年龄对 result <- df %>% group_by(PTNUM) %>% summarise( # 处理1→2转移 `1-2` = ifelse(any(STATE == 1) & any(STATE == 2) & max(which(STATE == 1)) < min(which(STATE == 2)), paste0("(", max(AGE[STATE == 1]), ",", min(AGE[STATE == 2]), ")"), NA), # 处理2→3转移 `2-3` = ifelse(any(STATE == 2) & any(STATE == 3), { first_3_pos <- min(which(STATE == 3)) last_2_before_3 <- max(AGE[STATE == 2 & seq_along(STATE) < first_3_pos]) paste0("(", last_2_before_3, ",", min(AGE[STATE == 3]), ")") }, NA), # 处理3→2转移 `3-2` = ifelse(any(STATE == 3) & any(STATE == 2 & seq_along(STATE) > min(which(STATE == 3))), { first_2_after_3_pos <- min(which(STATE == 2 & seq_along(STATE) > min(which(STATE == 3)))) last_3_before_2 <- max(AGE[STATE == 3 & seq_along(STATE) < first_2_after_3_pos]) age_2_after_3 <- AGE[first_2_after_3_pos] paste0("(", last_3_before_2, ",", age_2_after_3, ")") }, NA) ) %>% ungroup() # 查看结果 print(result)
代码逻辑说明
- 数据构造:将原始数据转换为
tibble格式,便于后续处理。 - 分组处理:按
PTNUM分组后,针对每个个体分别计算三种转移:- 1→2转移:先验证是否存在先1后2的状态序列,满足则取最后一次1的年龄和首次2的年龄组合。
- 2→3转移:找到首次出现3的位置,取该位置之前最后一次2的年龄,结合首次3的年龄生成组合。
- 3→2转移:找到首次在3之后出现2的位置,取该位置之前最后一次3的年龄,结合此次2的年龄生成组合。
- 结果输出:最终生成符合预期的结构化表格。
内容的提问来源于stack exchange,提问作者Hari
相关产品推荐
相关产品推荐

