Pandas新增列匹配shipped_qty≥qty_needed对应的ship_date
实现方案
核心逻辑是先计算发货表的累计发货总量,再用pandas.merge_asof做阈值匹配,自动找到第一个累计发货量≥订单所需累计量的对应发货日期,不需要写多层循环,大数据量下性能远高于手写for循环。
步骤1:导入依赖并构造示例数据
import pandas as pd # 订单表 df_order = pd.DataFrame({ 'qty_ordered': [2,3,1,1,4,3,1,3,20], 'qty_needed': [2,5,6,7,11,14,15,18,38] }) # 发货表 df_ship = pd.DataFrame({ 'shipped_qty': [10,24,42], 'ship_date': ['1/20/2022','2/20/2022','3/20/2022'] })
步骤2:预处理发货表,计算累计发货量
注意实际业务中如果发货表日期乱序,必须先按发货日期升序排序,再计算累计和:
# 按发货日期升序排序 df_ship = df_ship.sort_values('ship_date') # 计算截至每个发货日期的累计总发货量 df_ship['cum_shipped'] = df_ship['shipped_qty'].cumsum()
预处理后的发货表内容:
| shipped_qty | ship_date | cum_shipped |
|---|---|---|
| 10 | 1/20/2022 | 10 |
| 24 | 2/20/2022 | 34 |
| 42 | 3/20/2022 | 76 |
步骤3:阈值匹配关联发货日期
merge_asof是pandas专门处理区间关联、阈值匹配场景的方法,这里指定direction='forward'即可匹配到第一个累计发货量≥订单需量的发货记录:
# merge_asof要求关联键必须升序排列,先对订单表排序 df_order = df_order.sort_values('qty_needed') # 执行匹配 result = pd.merge_asof( df_order, df_ship[['cum_shipped', 'ship_date']], left_on='qty_needed', right_on='cum_shipped', direction='forward' ).drop(columns=['cum_shipped']) # 删除计算用的辅助列
最终输出
打印result即可得到预期结果:
qty_ordered qty_needed ship_date 0 2 2 1/20/2022 1 3 5 1/20/2022 2 1 6 1/20/2022 3 1 7 1/20/2022 4 4 11 2/20/2022 5 3 14 2/20/2022 6 1 15 2/20/2022 7 3 18 2/20/2022 8 20 38 3/20/2022
补充:如果坚持用for循环实现,逻辑是先存好发货累计值和对应日期的列表,遍历每一行qty_needed时,遍历累计发货列表找到第一个≥当前值的日期赋值即可,但数据量超过10万行时性能会比merge_asof差一个数量级,不推荐使用。
内容的提问来源于stack exchange,提问作者Hannah
相关产品推荐
相关产品推荐

