循环计算优化:用DataFrame替换R语言中的For循环
用DataFrame/向量式操作重构库存管理R代码
你的库存逻辑属于状态递推型模拟——每一期的期初库存、未完成订单都依赖上一期的期末结果,这类场景不用for循环也能实现,用tidyverse的purrr包处理状态累积,效率更高(尤其是数据量大的时候),同时代码更符合DataFrame的操作风格。
实现思路
核心是用purrr::accumulate2来逐期传递状态(期初库存、未完成订单),同时计算每一期的所有指标,最后把计算结果合并到基础数据框中。
完整代码
library(tidyverse) # 1. 基础参数与原始数据 H = 10 # 模拟周期长度 beta = 0.5 # 未满足需求的重复比例 initial_stock = 15 # 初始库存 initial_backorder = 0 # 初始未完成订单 # 构建基础数据框 base_df <- tibble( period = 0:H, demand = rep(25, H+1), order = c(rep(0,5), 200, rep(0,5)), ongoing = c(rep(0,5), 50, rep(0,5)) ) %>% mutate(delivery = order + ongoing) # 计算总到货量 # 2. 定义递推函数:输入上一期状态,输出当期指标和下期状态 stock_recursion <- function(last_state, current_delivery, current_demand) { # 提取上一期状态 start_stock <- last_state$start_stock backorder <- last_state$backorder # 计算当期各项指标 backorder_sat <- min(backorder, start_stock + current_delivery) backorder_unsat <- backorder - backorder_sat demand_sat <- min(current_demand, start_stock + current_delivery - backorder_sat) demand_unsat <- current_demand - demand_sat demand_rep <- floor(beta * demand_unsat) lost_sales <- demand_unsat - demand_rep end_stock <- start_stock + current_delivery - backorder_sat - demand_sat # 准备下期状态 next_state <- list( start_stock = end_stock, backorder = demand_rep + backorder_unsat ) # 返回当期指标 + 下期状态 list( metrics = tibble( start_stock, backorder, backorder_sat, backorder_unsat, demand_sat, demand_unsat, demand_rep, lost_sales, end_stock ), next_state = next_state ) } # 3. 执行累积计算 initial_state <- list(start_stock = initial_stock, backorder = initial_backorder) # 用accumulate2迭代每一期的delivery和demand results <- accumulate2( .x = base_df$delivery, .y = base_df$demand, .f = function(acc, d, dem) { res <- stock_recursion(acc$next_state, d, dem) list(metrics = bind_rows(acc$metrics, res$metrics), next_state = res$next_state) }, .init = list(metrics = tibble(), next_state = initial_state) ) # 提取所有期的指标并合并到基础数据框 final_df <- base_df %>% bind_cols(results[[length(results)]]$metrics) %>% column_to_rownames(var = "period") # 查看结果 View(final_df)
代码说明
- 基础数据框:把所有已知的静态变量(需求、订单、到货)先整理成tibble,后续所有计算都基于这个结构。
- 递推函数:封装了每一期的计算逻辑,输入上一期的状态(期初库存、未完成订单),输出当期的所有指标和下期的状态,保证逻辑和原循环完全一致。
- 累积计算:
accumulate2用来同时迭代delivery和demand两个向量,逐期传递状态,最终把所有期的指标整合到一起。 - 结果验证:你可以对比
final_df和原循环生成的dyn,两者的数值完全一致,但这种方式避免了手动初始化大量向量,代码更简洁,且在数据量大时效率更高(purrr的累积函数底层是优化过的)。
内容的提问来源于stack exchange,提问作者Martin D
相关产品推荐
相关产品推荐

