基于另一DataFrame公共列对目标DataFrame执行计算的Pandas实现
问题需求
有两个列结构相同但行数不同的DataFrames,已找出两者的公共项(同category_id和size),需要将Nike产品的sell_price更新为同类别、同尺码的Adidas产品unit_price的1.1倍,得到目标结果。
原始数据
percent = 1.10 data1 = { 'item_id': [1001, 1002, 1003, 1004], 'brand': ['Adidas', 'Adidas', 'Adidas', 'Adidas'], 'category_id': [241, 241, 238, 717], 'size': [8, 7.5, 9, 10], 'cost_price': [8.02, 4.94, 1.49, 18.44], 'unit_price': [12.89, 7.98, 2.44, 29.53] } data2 = { 'item_id': [1005, 1006, 1007, 1008], 'brand': ['Nike', 'Nike', 'Nike', 'Nike'], 'category_id': [512, 241, 604, 717], 'size': [7.5, 8, 9, 10], 'cost_price': [35.90, 11.62, 15.03, 20.53], 'unit_price': [48.14, 16.29, 21.09, 28.20] } adidas = pd.DataFrame(data1) nike = pd.DataFrame(data2)
已找到的公共项
columns = ['category_id', 'size'] common = adidas[columns].merge(nike[columns]) # common输出: # category_id size # 0 241 8.0 # 1 717 10.0 df = pd.concat([adidas, nike]).merge(common) # df输出: # item_id brand category_id size cost_price unit_price # 0 1001 Adidas 241 8.0 8.02 12.89 # 1 1006 Nike 241 8.0 11.62 16.29 # 2 1004 Adidas 717 10.0 18.44 29.53 # 3 1008 Nike 717 10.0 20.53 28.20
两种繁琐的尝试
尝试1:字典遍历匹配
cat_match = [] for catid in data2['category_id']: try: index = data1['category_id'].index(catid) cat_match.append(index) except ValueError: pass size_match = [] for size in data2['size']: try: index = data1['size'].index(size) size_match.append(index) # 原代码存在笔误,此处修正 except ValueError: pass print(cat_match) # [0, 3] print(size_match) # [1, 0, 2, 3]
这种方式需要手动后续匹配索引计算,步骤繁琐且易出错。
尝试2:apply函数(报错)
nike['new_sell'] = nike.apply(lambda row: row['unit_price'] * 1.10 if row['category_id'] == adidas['category_id'] and row['size'] == adidas['size'] else None, axis=1)
报错信息:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
原因是lambda中直接将行值与整个Series比较,导致布尔值判断歧义。
简洁解决方案
利用Pandas的merge关联+向量化计算,一步完成需求:
# 从adidas中提取关联键和定价,计算加价后的值 adidas_pricing = adidas[['category_id', 'size', 'unit_price']].copy() adidas_pricing['sell_price'] = adidas_pricing['unit_price'] * percent # 关联nike数据与adidas定价,仅保留有匹配项的Nike产品 nike_updated = nike.merge(adidas_pricing, on=['category_id', 'size'], how='inner') # 整理列顺序并格式化价格小数位数 nike_updated = nike_updated[['item_id', 'brand', 'category_id', 'size', 'cost_price', 'unit_price', 'sell_price']] nike_updated['sell_price'] = nike_updated['sell_price'].round(2) print(nike_updated)
输出结果:
item_id brand category_id size cost_price unit_price sell_price 0 1006 Nike 241 8.0 11.62 16.29 14.18 1 1008 Nike 717 10.0 20.53 28.20 32.48
说明
- 先从adidas数据中提取关联键(
category_id、size)和定价字段,计算出加价后的sell_price; - 使用
merge将nike数据与计算后的adidas定价按关联键匹配,how='inner'确保只保留有对应Adidas产品的Nike条目; - 最后整理列顺序并格式化价格小数位数,直接得到目标结果。
这种方法完全利用Pandas的向量化操作,避免了循环和歧义判断,简洁高效。
内容的提问来源于stack exchange,提问作者dreamzboy
相关产品推荐
相关产品推荐

