如何使用Pandas制作库存登记台账并计算指定日期的期末结存余额
Pandas库存台账计算报错修复方案
错误原因
你遇到的AttributeError核心原因是:shift()是Pandas DataFrame/整列Series才支持的方法,你在逐行遍历main_df时,拿到的row是单行数据对象,不存在shift方法。
另外你的代码还存在3个隐藏逻辑错误:
result.sort_values(by='Date')默认不修改原对象,你没有赋值或者加inplace=True,排序结果完全未生效- 遍历
tolo/frlo拼接表给main_df赋值时,你直接对整列赋值(main_df['Received'] = row['Quantity']),会导致整列被最后一行的数值覆盖,根本不会逐行写入对应数据 - 逐行遍历计算库存的效率极低,完全可以用Pandas向量化操作替代,无需循环
修复后完整实现代码
import pandas as pd # 你的仓库名变量,示例为dkl-kunjakant godown_name = 'dkl-kunjakant' # 1. 分别给出入库表打标记,提前生成Received、Dispatched列 tolo['Received'] = tolo['Quantity'] tolo['Dispatched'] = 0 frlo['Dispatched'] = frlo['Quantity'] frlo['Received'] = 0 # 2. 拼接两张表、处理日期、按日期排序(注意sort_values要赋值) result = pd.concat([tolo, frlo], ignore_index=True) result['Date'] = pd.to_datetime(result['Date']) result = result.sort_values(by='Date').reset_index(drop=True) # 3. 计算库存,全向量化操作无需遍历 # 期初库存 = 上期期末结存,第一行期初为0 result['Opening Stock'] = (result['Received'] - result['Dispatched']).cumsum().shift(1).fillna(0) result['Total'] = result['Opening Stock'] + result['Received'] result['Closing Balance'] = result['Total'] - result['Dispatched'] # 4. 筛选需要的列重命名即可得到最终台账 main_df = result[['Date', 'Opening Stock', 'Received', 'Total', 'Dispatched', 'Closing Balance', 'Challan No', 'Remark']].rename(columns={'Remark':'Remarks'}) print(main_df)
计算结果验证
基于你提供的示例数据,最终输出结果如下:
| Date | Opening Stock | Received | Total | Dispatched | Closing Balance | Challan No | Remarks |
|---|---|---|---|---|---|---|---|
| 2021-09-01 | 0 | 1000 | 1000 | 145 | 855 | 345 | ert |
| 2021-09-01 | 855 | 0 | 855 | 145 | 710 | 236 | asa |
| 2021-09-16 | 710 | 500 | 1210 | 0 | 1210 | 124 | hji |
| 2021-09-23 | 1210 | 0 | 1210 | 40 | 1170 | 540 | rty |
| 2021-09-24 | 1170 | 0 | 1170 | 50 | 1120 | 10 | hji |
如果需要按日期聚合每日总出入和结存,额外增加一步按Date分组求和即可。
内容的提问来源于stack exchange,提问作者Scrappy Coco
相关产品推荐
相关产品推荐

