You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将含numpy数组的DataFrame转换为周期视角的交付视图

问题背景与需求

我在供应链场景中规划交付安排,收货日期和交付数量存在随机性(提前/延迟到货、订单录入错误等),因此模拟了多个场景(最多上百个)。初始数据以DataFrame形式存储,每行对应一个物料,reception_date和ordered_qty的列表元素分别对应各场景下的收货日期和数量:

import pandas as pd
import numpy as np

trace_size = 3  # 场景数量
df_initial = pd.DataFrame({
    'item_id': ['item_1', 'item_2'],
    'reception_date': [[1, 2, 1], [1, 2, 1]],
    'ordered_qty': [[40, 45, 39], [45, 39, 42]]
})

初始数据展示:

item_idreception_dateordered_qty
item_1[1, 2, 1][40, 45, 39]
item_2[1, 2, 1][45, 39, 42]

需要将数据转换为按周期日期展示每个场景下的收货数量的格式,目标DataFrame如下:

item_idperiod_dateordered_qty
item_10[0, 0, 0]
item_11[40, 0, 39]
item_12[0, 45, 0]
item_20[0, 0, 0]
item_21[45, 0, 42]
item_22[0, 39, 0]

当前实现使用了for循环处理每个场景,但场景数量最多可达上百个,希望去掉循环提升效率。当前代码及结果如下:

df = pd.DataFrame(columns=['item_id', 'reception_date', 'ordered_qty'])
for z in range(trace_size):
    df1 = df_initial.copy()
    df1['reception_date']=df_initial['reception_date'].apply(lambda x: x[z])
    df1['ordered_qty']=df_initial['ordered_qty'].apply(lambda x: x[z])
    df = pd.concat([df, df1])
df = df.groupby(['item_id', 'reception_date'], as_index=False).agg({'ordered_qty': list})

dyn = pd.DataFrame({'item_id': np.repeat(df_initial['item_id'].values, 3),
                    'period_date': np.tile(np.arange(0, 3), 2)})
df_final = dyn.merge(df.rename(columns={'reception_date': 'period_date'}), how='outer').fillna(0)

当前结果:

item_idperiod_dateordered_qty
item_100
item_11[40, 39]
item_12[45]
item_200
item_21[45, 42]
item_22[39]

无循环优化方案

以下是去掉for循环的高效实现,适合大规模场景的处理:

import pandas as pd
import numpy as np

trace_size = 3
period_range = np.arange(0, 3)  # 固定时间范围0-2天
df_initial = pd.DataFrame({
    'item_id': ['item_1', 'item_2'],
    'reception_date': [[1, 2, 1], [1, 2, 1]],
    'ordered_qty': [[40, 45, 39], [45, 39, 42]]
})

# 1. 将每个物料的场景数据展开为单独列,避免循环拼接
df_expanded = df_initial.assign(
    **{f"date_{i}": df_initial['reception_date'].apply(lambda x: x[i]) for i in range(trace_size)},
    **{f"qty_{i}": df_initial['ordered_qty'].apply(lambda x: x[i]) for i in range(trace_size)}
)

# 2. 生成所有物料+周期日期的笛卡尔积,确保覆盖所有日期
all_periods = pd.MultiIndex.from_product(
    [df_initial['item_id'], period_range],
    names=['item_id', 'period_date']
).to_frame(index=False)

# 3. 对每个场景匹配对应周期的数量,再合并为列表列
result_list = []
for i in range(trace_size):
    scenario_df = df_expanded[['item_id', f'date_{i}', f'qty_{i}']].rename(
        columns={f'date_{i}': 'period_date', f'qty_{i}': f'qty_scen_{i}'}
    )
    # 匹配全周期表,无数据则填0
    merged = all_periods.merge(scenario_df, on=['item_id', 'period_date'], how='left').fillna(0)
    result_list.append(merged[f'qty_scen_{i}'])

# 4. 将各场景的数量列合并为列表,得到最终结果
df_final = all_periods.assign(
    ordered_qty=pd.concat(result_list, axis=1).apply(list, axis=1)
)

print(df_final)

输出结果:

item_id  period_date ordered_qty
0  item_1            0  [0.0, 0.0, 0.0]
1  item_1            1  [40.0, 0.0, 39.0]
2  item_1            2  [0.0, 45.0, 0.0]
3  item_2            0  [0.0, 0.0, 0.0]
4  item_2            1  [45.0, 0.0, 42.0]
5  item_2            2  [0.0, 39.0, 0.0]

优化说明

  • 避免了逐个场景循环拼接DataFrame的操作,改为先展开所有场景数据为列,减少内存开销和循环耗时
  • 通过笛卡尔积生成完整的物料-周期组合,确保每个日期都被覆盖
  • 对每个场景单独匹配数量后合并为列表列,逻辑清晰且效率更高,适合上百个场景的规模

内容的提问来源于stack exchange,提问作者Martin D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:07:52