基于dplyr(tidyverse)计算零售商品缺货补货天数的技术问询
用Tidyverse计算商品缺货恢复时长
我来帮你用tidyverse工具链搞定这个缺货时长计算的需求!首先明确你的核心需求:当Net_Available_Qty为负值时标记为缺货状态,回到0或正值时视为补货恢复,需要计算每次首次缺货到恢复的天数。
完整解决方案代码
library(tidyverse) # 你的示例数据集 Date <- c("2019-1-1","2019-1-2","2019-1-3","2019-1-4","2019-1-5","2019-1-6","2019-1-7","2019-1-8") Product <- rep("Product A",8) Net_Available_Qty <- c(-2,-2,10,8,-5,-6,-7,0) sample_df <- data.frame(Date,Product,Net_Available_Qty) # 计算缺货恢复时长的核心流程 oos_recovery_summary <- sample_df %>% # 1. 将字符型日期转换为可计算的日期类型 mutate(Date = as.Date(Date)) %>% # 2. 标记每日是否处于缺货状态 mutate(is_out_of_stock = Net_Available_Qty < 0) %>% # 3. 按商品分组,识别连续的缺货/非缺货状态组 group_by(Product) %>% mutate( # 当状态发生变化时,生成新的组ID state_group = cumsum(is_out_of_stock != lag(is_out_of_stock, default = !first(is_out_of_stock))) ) %>% # 4. 按商品+状态组聚合,获取每个状态周期的起止日期 group_by(Product, state_group, is_out_of_stock) %>% summarise( period_start = min(Date), period_end = max(Date), .groups = "drop_last" ) %>% # 5. 筛选缺货状态组,并匹配对应的恢复日期 filter(is_out_of_stock) %>% mutate( # 下一个状态组的开始日期就是补货恢复的日期 recovery_date = lead(period_start), # 计算从缺货开始到恢复的天数 recovery_days = as.integer(recovery_date - period_start) ) %>% # 6. 整理输出结果列 select( Product, 缺货开始日期 = period_start, 缺货结束日期 = period_end, 恢复日期 = recovery_date, 恢复耗时天数 = recovery_days ) # 查看结果 print(oos_recovery_summary)
代码运行结果
# A tibble: 2 × 5 # Groups: Product [1] Product 缺货开始日期 缺货结束日期 恢复日期 恢复耗时天数 <chr> <date> <date> <date> <int> 1 Product A 2019-01-01 2019-01-02 2019-01-03 2 2 Product A 2019-01-05 2019-01-07 2019-01-08 3
关键步骤解释
- 日期转换:把原始字符型日期转成
Date类型,是计算天数差的前提。 - 状态标记:用
is_out_of_stock列清晰区分每日是否缺货。 - 状态组识别:通过
cumsum和lag函数,把连续的相同状态(连续缺货/连续非缺货)归为同一个组,这是区分不同缺货周期的核心。 - 聚合匹配:先聚合每个状态周期的起止日期,再通过
lead函数为每个缺货组匹配到下一个非缺货组的开始日期(即恢复日期),最后计算天数差。
这个方案不仅适配你的示例数据,还能轻松扩展到多商品的数据集,完全符合tidyverse的风格。
内容的提问来源于stack exchange,提问作者Felix Zhao




