如何基于Pandas DataFrame按仓、司、SKU计算每日安全库存
解决多分组下的每日安全库存计算问题
这是个很典型的分组滚动计算场景,咱们用Pandas的分组(groupby)结合滚动窗口函数就能高效解决,完全不用手动遍历每个分组,既简洁又适配大数据集。
先明确需求逻辑
根据你的描述,安全库存的计算公式是:
当日SS = (当日 + 次日 + 第三日的Demand总和) / 当日Balance
只有当当前日期后面还有至少两天数据时,才计算SS(比如示例中10/3、10/4没有SS,因为凑不够3天的Demand)
完整代码实现
import pandas as pd # 1. 先处理日期格式(确保是datetime类型,避免排序错误) df['ActivityDate'] = pd.to_datetime(df['ActivityDate'], format='%d/%m/%Y') # 2. 按分组键+日期排序,保证每个分组内的日期是顺序的 df = df.sort_values(['DepotName', 'Company', 'SKU', 'ActivityDate']) # 3. 分组计算滚动3天的Demand总和(仅当窗口内有3个数据时才返回结果) df['_3day_demand_sum'] = df.groupby(['DepotName', 'Company', 'SKU'])['Demand'] \ .rolling(window=3, min_periods=3) \ .sum() \ .reset_index(level=[0,1,2], drop=True) # 4. 计算安全库存SS,无有效数据时留空 df['SS'] = df.apply(lambda row: round(row['_3day_demand_sum'] / row['Balance'], 2) if pd.notna(row['_3day_demand_sum']) else None, axis=1) # 5. 清理中间辅助列(可选) df = df.drop('_3day_demand_sum', axis=1) # 查看结果 print(df)
代码关键步骤解释
- 日期处理与排序:必须把
ActivityDate转为datetime类型,并且按分组键+日期排序,否则滚动窗口会计算混乱。 - 分组滚动求和:
rolling(window=3, min_periods=3)表示取当前行及后续共3行的Demand求和,min_periods=3确保只有凑够3天数据时才返回结果,正好对应我们需要计算SS的日期。 - SS计算:用
apply判断滚动求和的结果是否有效,有效则除以当日Balance并保留两位小数,否则设为None(对应示例中的空值)。
结果验证
运行代码后,你的示例数据会输出和预期完全一致的结果:
ActivityDate DepotName Company SKU Balance Demand SS 0 2017-10-01 Depot1 A SKU1 10 1 0.30 1 2017-10-02 Depot1 A SKU1 9 1 0.33 2 2017-10-03 Depot1 A SKU1 8 1 NaN 3 2017-10-04 Depot1 A SKU1 7 1 NaN
这种方法是向量化操作,比手动循环每个分组效率高得多,完全适合多仓库、多公司、多SKU的大数据集。
内容的提问来源于stack exchange,提问作者Ahamed Moosa
相关产品推荐
相关产品推荐

