如何在Python DataFrame的itertuples循环中更新当前记录?
解决DataFrame循环更新Qty字段的问题
问题根源
itertuples()返回的是不可变的namedtuple对象,你直接修改rowB.Qty只是修改了这个临时对象的属性,完全不会同步到原DataFramedf_B中,这就是你无法更新的核心原因。
推荐方案:用Pandas向量化操作(高效)
Pandas的设计初衷就是避免循环,向量化操作处理数据的效率远高于循环。你的需求是按PO和Item匹配,将df_A的Qty从df_B对应行的Qty中扣除,可以这么实现:
import pandas as pd df_A = pd.read_csv('file_A.csv', header=0) df_B = pd.read_csv('file_B.csv', header=0) # 对df_A按PO+Item分组,计算每个组合的总扣除量(适配同PO+Item有多条记录的情况) df_A_total = df_A.groupby(["PO", "Item"])["Qty"].sum().reset_index() # 合并df_B和分组后的df_A,匹配对应行 merged_df = df_B.merge(df_A_total, on=["PO", "Item"], how="left", suffixes=("", "_deduct")) # 计算更新后的Qty:没有匹配到的行保持原数量 merged_df["Qty"] = merged_df["Qty"] - merged_df["Qty_deduct"].fillna(0) # 恢复原索引(如果需要) df_B = merged_df.set_index(["PO", "Item"])
保留循环逻辑的方案(仅适用于小数据量)
如果因为业务逻辑必须保留循环,不要用itertuples()遍历df_B,直接通过索引定位行进行更新:
import pandas as pd df_A = pd.read_csv('file_A.csv', header=0) df_B = pd.read_csv('file_B.csv', header=0) df_B = df_B.set_index(["PO", "Item"]) for rowA in df_A.itertuples(): # 构造匹配的索引键 match_key = (rowA.PO, rowA.Item) # 检查该键是否存在于df_B的索引中 if match_key in df_B.index: # 直接通过索引更新Qty字段 df_B.loc[match_key, "Qty"] -= rowA.Qty # 执行你的其他业务逻辑 # ...
注意事项
- 如果
df_B中同一个PO+Item对应多行,上述循环会把rowA.Qty重复扣除每一行。如果需要按行精准匹配扣除,需补充额外匹配条件(比如行号),但这种场景仍优先推荐向量化操作。 - 循环操作在数据量大时性能极差,非必要不要使用。
内容的提问来源于stack exchange,提问作者TheHorn
相关产品推荐
相关产品推荐

