在R数据框分组内获取滞后值:解决连续失业期最后工资问题
匹配雇主-雇员数据集的失业期工资填充方案
数据集背景
处理包含员工和企业层面变量的匹配雇主-雇员数据集,部分数据示例如下:
R代码生成数据
df <- structure(list(WorkerID = c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L), FirmID = c(1234L, 1234L, 1234L, 1234L, 1234L, 4321L, 4321L, 9678L, 9678L, 4321L, 5678L, 5678L, 5678L), Year = c(2003L, 2004L, 2005L, 2004L, 2005L, 2006L, 2007L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L), Wage = c(1000L, 1000L, 1000L, 1200L, 0L, 1250L, 1250L, 735L, 0L, 0L, 780L, 780L, 0L), Separation = c(0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 1L, 1L, 0L, 0L, 1L)), class = "data.frame", row.names = c(NA, -13L))
数据表格展示
| WorkerID | FirmID | Year | Wage | Separation |
|---|---|---|---|---|
| 1 | 1234 | 2003 | 1000 | 0 |
| 1 | 1234 | 2004 | 1000 | 0 |
| 1 | 1234 | 2005 | 1000 | 0 |
| 2 | 1234 | 2004 | 1200 | 0 |
| 2 | 1234 | 2005 | 0 | 1 |
| 2 | 4321 | 2006 | 1250 | 0 |
| 2 | 4321 | 2007 | 1250 | 0 |
| 3 | 9678 | 2003 | 735 | 0 |
| 3 | 9678 | 2004 | 0 | 1 |
| 3 | 4321 | 2005 | 0 | 1 |
| 3 | 5678 | 2006 | 780 | 0 |
| 3 | 5678 | 2007 | 780 | 0 |
| 3 | 5678 | 2008 | 0 | 1 |
需求说明
Separation变量表示员工当年是否离职(值为1代表失业),员工可能存在连续多期失业的情况。需要生成一个last_wage变量:
- 若员工处于就业状态(
Separation == 0),记录当前工资 - 若员工处于失业状态(
Separation == 1),记录其最后一次获得的工资
例如:
- 员工2在2005年失业,
last_wage应为2004年的1200 - 员工3在2004和2005年连续失业,这两年的
last_wage均为2003年的735
现有代码仅能处理最多一期失业的情况,无法覆盖连续多期失业场景:
df %>% group_by(WorkerID) %>% mutate(last_wage = ifelse(Separation == 1 & lag(Separation)==0, lag(Wage),Wage))
解决方案
使用dplyr结合tidyr的fill()函数,可轻松处理任意连续失业期的工资填充:
library(dplyr) library(tidyr) df_processed <- df %>% # 按员工分组,确保每个员工的工资填充独立进行 group_by(WorkerID) %>% # 创建临时变量:仅保留就业期的工资,失业期设为NA mutate(temp_wage = ifelse(Separation == 0, Wage, NA)) %>% # 向下填充NA值,让连续失业期继承上一次就业的工资 fill(temp_wage, .direction = "down") %>% # 生成最终的last_wage变量 mutate(last_wage = ifelse(Separation == 0, Wage, temp_wage)) %>% # 移除临时变量 select(-temp_wage) %>% ungroup() # 查看处理后的数据 print(df_processed)
处理后结果展示
| WorkerID | FirmID | Year | Wage | Separation | last_wage |
|---|---|---|---|---|---|
| 1 | 1234 | 2003 | 1000 | 0 | 1000 |
| 1 | 1234 | 2004 | 1000 | 0 | 1000 |
| 1 | 1234 | 2005 | 1000 | 0 | 1000 |
| 2 | 1234 | 2004 | 1200 | 0 | 1200 |
| 2 | 1234 | 2005 | 0 | 1 | 1200 |
| 2 | 4321 | 2006 | 1250 | 0 | 1250 |
| 2 | 4321 | 2007 | 1250 | 0 | 1250 |
| 3 | 9678 | 2003 | 735 | 0 | 735 |
| 3 | 9678 | 2004 | 0 | 1 | 735 |
| 3 | 4321 | 2005 | 0 | 1 | 735 |
| 3 | 5678 | 2006 | 780 | 0 | 780 |
| 3 | 5678 | 2007 | 780 | 0 | 780 |
| 3 | 5678 | 2008 | 0 | 1 | 780 |
逻辑说明
- 分组处理:按
WorkerID分组,保证每个员工的工资填充逻辑独立 - 临时变量标记:用
temp_wage筛选出所有就业期的工资,失业期设为NA,方便后续填充 - 向下填充:
fill()函数会将最近的非NA值向下覆盖所有连续的NA,完美解决连续失业期的工资继承问题 - 生成最终变量:区分就业和失业状态,给
last_wage赋值
内容的提问来源于stack exchange,提问作者lisbonscot
相关产品推荐
相关产品推荐

