高效实现基于多DataFrame关联的df1 Price列计算
高效计算Pandas DataFrame的Price列
问题说明
现有三个Pandas DataFrame(注:原代码存在变量名混淆,已修正对应关系):
- df1:包含周期、待计算的Price列、年份(years)和季度(quarters)
- df_year_price:存储各年份对应的price值(原代码注释为df2,实际赋值给了df3)
- df_quarter_weight:存储各季度对应的weights值(原代码注释为df3,实际赋值给了df2)
需求:计算df1的Price列,规则为每行Price = 对应年份的price × 对应季度的weights,例如df1第一行years=2024、quarters=2,Price = 244 × 0.81(原示例中473.26为2023年price,对应错误,已修正)。
高效实现方案
避免低效的逐行循环,使用Pandas的矢量化操作(merge或map),以下是两种可行方案:
方案1:通过Merge关联数据后计算
通过两次merge分别关联季度权重和年度价格,再执行列相乘:
import pandas as pd import numpy as np # 修正后的DataFrame定义 # df1定义 data = {'Period': ['2024-04-O1', '2024-07-O1', '2024-10-O1', '2025-01-O1', '2025-04-O1', '2025-07-O1', '2025-10-O1', '2026-01-O1', '2026-04-O1', '2026-07-O1', '2026-10-O1', '2027-01-O1', '2027-04-O1', '2027-07-O1', '2027-10-O1', '2028-01-O1', '2028-04-O1', '2028-07-O1', '2028-10-O1'], 'Price': ['NaN']*19, 'years': [2024,2024,2024,2025,2025,2025,2025,2026,2026,2026,2026,2027,2027,2027,2027,2028, 2028,2028,2028], 'quarters':[2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4] } df1 = pd.DataFrame(data=data) # 年度价格表(原注释df2,修正变量名) df_year_price = pd.DataFrame({ 'price': [473.26,244,204,185, 152, 157], 'year': [2023, 2024, 2025, 2026, 2027, 2028] }) # 季度权重表(原注释df3,修正变量名) df_quarter_weight = pd.DataFrame({ 'quarters': [1,2,3,4], 'weights': [1.22, 0.81, 0.83, 1.12] }) # 关联季度权重 df1 = df1.merge(df_quarter_weight, on='quarters', how='left') # 关联年度价格 df1 = df1.merge(df_year_price, left_on='years', right_on='year', how='left') # 计算Price并清理临时列 df1['Price'] = df1['price'] * df1['weights'] df1 = df1.drop(['weights', 'price', 'year'], axis=1) print(df1)
方案2:使用Map映射取值后计算
将年度价格、季度权重转换为字典,通过Series的map方法直接映射取值,再相乘:
# 基于修正后的DataFrame定义 # 转换为映射字典 year_price_dict = df_year_price.set_index('year')['price'].to_dict() quarter_weight_dict = df_quarter_weight.set_index('quarters')['weights'].to_dict() # 映射并计算Price df1['Price'] = df1['years'].map(year_price_dict) * df1['quarters'].map(quarter_weight_dict) print(df1)
方案优势
两种方案均采用Pandas矢量化操作,避免了Python级别的逐行循环,在数据量较大时性能远高于循环实现,同时代码更简洁易维护。
内容的提问来源于stack exchange,提问作者hermann joel
相关产品推荐
相关产品推荐

