如何正确合并两个DataFrame并更新零值PurchasePrice?
问题原因
你遇到的行数爆炸问题,核心是df_purchase中存在重复的OrderItemSKU记录。当使用pd.merge时,每个重复的SKU都会和df_zero_purchase里的对应行匹配一次,导致笛卡尔积式的行数增长,最终出现近5万行的异常结果。
解决方案
以下是几种高效的更新方式,避免合并时的行数膨胀问题:
方案1:去重后映射更新
先对df_purchase按OrderItemSKU去重,确保每个SKU只保留一条有效价格记录,再通过映射替换df_zero_purchase中的零值:
# 对df_purchase去重,保留每个SKU的第一条记录(可根据业务调整为last()取最后一条) purchase_price_map = df_purchase.drop_duplicates(subset='OrderItemSKU', keep='first').set_index('OrderItemSKU')['PurchasePrice'] # 替换df_zero_purchase中PurchasePrice为0的行 df_zero_purchase['PurchasePrice'] = df_zero_purchase.apply( lambda row: purchase_price_map.get(row['OrderItemSKU'], row['PurchasePrice']), axis=1 )
方案2:使用combine_first自动填充
通过索引对齐,用combine_first自动用非零值覆盖零值:
# 将两个DataFrame按OrderItemSKU设为索引,方便对齐 df_zero_indexed = df_zero_purchase.set_index('OrderItemSKU') df_purchase_clean = df_purchase.drop_duplicates(subset='OrderItemSKU').set_index('OrderItemSKU') # 优先保留原数据的非零值,零值用df_purchase的对应值填充 df_updated = df_zero_indexed.combine_first(df_purchase_clean).reset_index()
方案3:使用update精准更新
直接定位零值行,用清理后的df_purchase数据更新:
# 清理df_purchase,确保每个SKU唯一 df_purchase_clean = df_purchase.drop_duplicates(subset='OrderItemSKU').set_index('OrderItemSKU') # 复制原数据避免修改原始文件 df_updated = df_zero_purchase.copy().set_index('OrderItemSKU') # 只更新PurchasePrice为0的行 mask = df_updated['PurchasePrice'] == 0 df_updated.loc[mask, 'PurchasePrice'] = df_purchase_clean['PurchasePrice'] # 恢复索引为普通列 df_updated = df_updated.reset_index()
补充说明
如果df_purchase中同一个SKU对应多个不同价格,需先明确业务规则:
- 取最新/最早价格:调整
drop_duplicates的keep参数 - 取平均价格:用
groupby聚合
# 示例:按SKU分组取平均价格 purchase_price_map = df_purchase.groupby('OrderItemSKU')['PurchasePrice'].mean().reset_index().set_index('OrderItemSKU')['PurchasePrice']
内容的提问来源于stack exchange,提问作者Orhan Dağ
相关产品推荐
相关产品推荐

