如何用Python修改符合条件的Pandas DataFrame行(BOM场景)
问题描述
我有一个包含价格信息的BOM(物料清单)Pandas DataFrame,数据如下:
| Assembly Level | Part Name | Price |
|---|---|---|
| 1 | FOOBARBAZQUX(主装配体) | 100 |
| 2 | FOO(零件) | 20 |
| 2 | BAR(零件) | 30 |
| 2 | BAZ(子装配体) | 25 |
| 3 | BAZ_1(BAZ子装配体的子零件) | 15 |
| 3 | BAZ_2(BAZ子装配体的子装配体) | 10 |
| 4 | BAZ_2_1(BAZ_2子装配体的子零件) | 10 |
| 2 | BOB(零件) | 14 |
| 2 | QUX(子装配体) | 0 |
| 3 | QUX_1(QUX子装配体的子零件) | 12 |
需求:如果存在价格不为0的子装配体,将其所有子项的价格替换为该父装配体的价格,期望结果如下:
| Assembly Level | Part Name | Price |
|---|---|---|
| 1 | FOOBARBAZQUX(主装配体) | 100 |
| 2 | FOO(零件) | 20 |
| 2 | BAR(零件) | 30 |
| 2 | BAZ(子装配体) | 25 |
| 3 | BAZ_1(BAZ子装配体的子零件) | 25 |
| 3 | BAZ_2(BAZ子装配体的子装配体) | 25 |
| 4 | BAZ_2_1(BAZ_2子装配体的子零件) | 25 |
| 2 | BOB(零件) | 14 |
| 2 | QUX(子装配体) | 0 |
| 3 | QUX_1(QUX子装配体的子零件) | 12 |
补充说明:通过Assembly Level区分子装配体:若第n行的Assembly Level数值小于后续行,则第n行为子装配体,后续行是其子项。例如,BAZ是级别2的子装配体,包含级别3的子项BAZ_1和BAZ_2;BAZ_2有级别4的子项BAZ_2_1,因此它也属于子装配体。BOB与BAZ的Assembly Level相同,不属于BAZ的子装配体。
解决方案
可以通过以下Python代码实现需求,核心用栈结构追踪嵌套的父装配体价格,遍历过程中完成子项价格替换:
import pandas as pd # 构建示例DataFrame data = { 'Assembly Level': [1,2,2,2,3,3,4,2,2,3], 'Part Name': [ 'FOOBARBAZQUX(主装配体)', 'FOO(零件)', 'BAR(零件)', 'BAZ(子装配体)', 'BAZ_1(BAZ子装配体的子零件)', 'BAZ_2(BAZ子装配体的子装配体)', 'BAZ_2_1(BAZ_2子装配体的子零件)', 'BOB(零件)', 'QUX(子装配体)', 'QUX_1(QUX子装配体的子零件)' ], 'Price': [100,20,30,25,15,10,10,14,0,12] } df = pd.DataFrame(data) # 用栈存储当前层级的父装配体信息(级别+价格) parent_stack = [] # 遍历每一行处理价格替换 for idx, row in df.iterrows(): current_level = row['Assembly Level'] current_price = row['Price'] # 弹出栈中级别 >= 当前级别的元素,确保栈顶是当前行的直接父级 while parent_stack and parent_stack[-1]['level'] >= current_level: parent_stack.pop() # 若存在有效父装配体(价格不为0),替换当前行价格 if parent_stack and parent_stack[-1]['price'] != 0: df.at[idx, 'Price'] = parent_stack[-1]['price'] # 将当前行的级别和价格入栈,作为后续子项的父级参考 parent_stack.append({'level': current_level, 'price': current_price}) # 打印处理后的结果 print(df)
代码逻辑说明
- 栈结构适配嵌套装配:通过栈维护当前层级的父装配体信息,遇到更低层级的行时,弹出栈中级别不小于当前级别的元素,保证栈顶始终是当前行的直接父装配体。
- 价格替换规则:如果栈顶的父装配体价格不为0,就将当前子项的价格替换为父装配体的价格;若父装配体价格为0,则保留子项原价格。
- 入栈更新父级:每一行处理完成后,将自身的级别和价格入栈,供后续更高层级的子项作为父级参考。
运行代码后,输出的DataFrame将完全符合需求中的预期结果。
内容的提问来源于stack exchange,提问作者Philip C
相关产品推荐
相关产品推荐

