R语言实现25年跨度下数据框状态值逐期迭代更新的方法
R实现25年个体状态逐期迭代模拟
实现思路
整体采用「单期更新逻辑封装+逐期迭代存储」的方案,避免迭代过程中数据覆盖导致的追溯困难,核心注意点:
- 所有个体每推进1期,年龄固定自增1,属于全局通用更新逻辑
- 两类状态跳转规则互斥,按条件匹配后执行对应字段更新,不满足跳转条件的个体除年龄外其余字段保持原值
- 规则1中计算薪资
sal时,必须使用exp_y自增后的新值计算,不能引用更新前的旧值,否则结果会出现系统性偏差 - 每一期的完整数据单独存储,最终可合并为带期数标识的长格式数据框,方便后续统计分析
可运行代码方案
首先构造符合字段要求的初始数据,可直接替换为自有真实数据集:
# 可选加载dplyr简化数据操作,核心逻辑无强依赖 library(dplyr) # 构造6条初始观测示例,字段与需求完全对齐 set.seed(123) # 固定随机种子方便结果复现 init_df <- tibble( age = sample(20:40, 6, replace = TRUE), sex = sample(c("male", "female"), 6, replace = TRUE), edu = sample(c("high_school", "bachelor", "master"), 6, replace = TRUE), statu = sample(c("em", "unem"), 6, replace = TRUE), exp_y = sample(0:10, 6, replace = TRUE), sal = ifelse(statu == "em", sample(3000:10000, 6, replace = TRUE), 0), cost = sample(2000:8000, 6, replace = TRUE), sal_a = ifelse(statu == "unem", sample(2000:9000, 6, replace = TRUE), 0), cost_a = ifelse(statu == "unem", sample(1000:7000, 6, replace = TRUE), 0) )
封装单期更新函数,输入为上一期数据框,输出为当期更新完成的数据框:
update_one_period <- function(last_period_df) { # 复制上一期数据作为当期基础,避免直接修改原数据 current_df <- last_period_df # 处理规则1:失业且预期薪资>预期成本 → 转为就业状态 rule1_idx <- which(current_df$statu == "unem" & current_df$sal_a > current_df$cost_a) if (length(rule1_idx) > 0) { # 严格按规则顺序更新,先调整exp_y再计算当期薪资 current_df$statu[rule1_idx] <- "em" current_df$age[rule1_idx] <- current_df$age[rule1_idx] + 1 current_df$exp_y[rule1_idx] <- current_df$exp_y[rule1_idx] + 1 current_df$sal[rule1_idx] <- current_df$sal_a[rule1_idx] * (1 + 0.19 * current_df$exp_y[rule1_idx]) current_df$cost[rule1_idx] <- current_df$cost_a[rule1_idx] current_df$sal_a[rule1_idx] <- 0 current_df$cost_a[rule1_idx] <- 0 } # 处理规则2:就业且当前薪资<当前成本 → 转为失业状态 rule2_idx <- which(current_df$statu == "em" & current_df$sal < current_df$cost) if (length(rule2_idx) > 0) { current_df$statu[rule2_idx] <- "unem" current_df$age[rule2_idx] <- current_df$age[rule2_idx] + 1 current_df$sal_a[rule2_idx] <- current_df$sal[rule2_idx] current_df$cost_a[rule2_idx] <- current_df$cost[rule2_idx] # exp_y保持原值无需修改 current_df$sal[rule2_idx] <- 0 current_df$cost[rule2_idx] <- 0 } # 处理不满足两类跳转规则的个体:仅年龄自增1,其余字段不变 other_idx <- setdiff(1:nrow(current_df), c(rule1_idx, rule2_idx)) if (length(other_idx) > 0) { current_df$age[other_idx] <- current_df$age[other_idx] + 1 } return(current_df) }
执行25期迭代,存储全周期结果:
# 初始化结果列表,初始期标记为period=0 sim_result <- list() sim_result[[1]] <- init_df %>% mutate(period = 0) # 逐期迭代25次 for (p in 1:25) { last_df <- sim_result[[p]] %>% select(-period) current_df <- update_one_period(last_df) %>% mutate(period = p) sim_result[[p+1]] <- current_df } # 合并所有期数为长表,可直接用于后续统计、绘图 final_sim_df <- bind_rows(sim_result)
如果不想依赖dplyr,可去掉开头的加载语句,初始数据构造改用data.frame(),最后合并结果替换为final_sim_df <- do.call(rbind, sim_result)即可,核心更新逻辑完全基于base R编写,无额外依赖。
结果校验提示
- 可给初始数据增加唯一
id列并在迭代中保留,抽查单一个体的全周期轨迹,确认状态跳转、字段更新符合规则 - 校验字段取值逻辑:就业状态下
sal_a/cost_a应为0,失业状态下sal/cost应为0,若出现非0值说明更新逻辑有疏漏
内容的提问来源于stack exchange,提问作者Majed
相关产品推荐
相关产品推荐

