如何为df1新增avg列:将观测mpg除以对应CAFE标准mpg?
高效实现多字段匹配计算mpg比值的方案
首先,先明确你的核心需求:给df1新增avg列,值为每行的观测mpg除以df2中同make、同model、同fuel的CAFE标准mpg。先梳理下你当前代码存在的问题,再给出更高效的实现方式:
输入数据回顾
df1 - 全国观测mpg数据
state make model fuel mpg FL honda fit diesel 43 FL honda fit gas 33 FL vw golf diesel 48 FL vw golf gas 35 FL ford fiesta diesel 40 FL ford fiesta gas 36 FL toyota corolla diesel 44 FL toyota corolla gas 38
df2 - CAFE标准数据
make model fuel mpg honda fit diesel 43 honda fit gas 33 vw golf diesel 48 vw golf gas 35 ford fiesta diesel 40 ford fiesta gas 36 toyota corolla diesel 44 toyota corolla gas 38 nissan sentra diesel 39 nissan sentra gas 29
当前代码的核心问题
- 筛选逻辑错误:连续三次对
df2用loc切片,每次都会覆盖之前的df3,最后df3只保留了fuel在fuel_list里的行,并没有同时满足make、model、fuel的筛选条件 - 效率极低:嵌套循环在大数据量下会非常慢,完全没有利用pandas的向量化优势
- 计算逻辑错误:
goal取的是df3.iloc[0]['mpg']的固定值,导致所有行的avg都是同一个值,根本没有实现“对应匹配”的需求
推荐的高效实现方法
方法1:用merge合并后计算(最直观)
通过多字段合并两个DataFrame,直接计算比值,这是最容易理解和维护的方式:
# 按make、model、fuel合并,保留df1的所有行,给两个mpg列加后缀区分 merged_df = df1.merge( df2, on=['make', 'model', 'fuel'], suffixes=('_observed', '_standard') ) # 计算avg列 merged_df['avg'] = merged_df['mpg_observed'] / merged_df['mpg_standard'] # 如果需要保留原df1的结构,直接把avg列赋值回去 df1['avg'] = merged_df['avg']
方法2:用字典映射+apply(轻量灵活)
把df2转换成字典,用(make, model, fuel)作为键,然后通过apply快速匹配计算:
# 将df2转换为多键字典,方便快速查找标准mpg cafe_mpg_map = df2.set_index(['make', 'model', 'fuel'])['mpg'].to_dict() # 对df1每行生成匹配键,计算比值 df1['avg'] = df1.apply( lambda row: row['mpg'] / cafe_mpg_map[(row['make'], row['model'], row['fuel'])], axis=1 )
方法3:用索引join(适合频繁匹配场景)
如果需要多次进行这类匹配,可以先把两个DataFrame的索引设为匹配字段,再通过join合并计算:
# 给两个DataFrame设置多字段索引 df1_indexed = df1.set_index(['make', 'model', 'fuel']) df2_indexed = df2.set_index(['make', 'model', 'fuel']) # 合并并计算avg df1_indexed['avg'] = df1_indexed['mpg'] / df2_indexed['mpg'] # 恢复原索引(如果需要) df1 = df1_indexed.reset_index()
这些方法的优势
- 效率高:所有操作都是pandas的向量化操作,比嵌套循环快几十到上百倍(数据量越大优势越明显)
- 逻辑精准:严格匹配每行对应的make、model、fuel,不会出现固定值错误
- 代码简洁:不需要硬编码特定的make/model列表,扩展性强
内容的提问来源于stack exchange,提问作者DLB
相关产品推荐
相关产品推荐

