基于Pandas计算月度环比变动的基数效应与新价格效应
用Pandas计算CPI数据的基数效应与新价格效应
Hey folks, 最近遇到一个需求:基于包含日期和月度环比(MoM)的CPI数据,计算基数效应(base_effect)和新价格效应(new_price_effect)。先给大家明确计算规则,再直接上可运行的Pandas代码实现。
计算规则先搞清楚
1. 基数效应(base_effect)
- 逻辑很明确:对于当年第N个月,基数效应是上一年第N+1个月到上一年12月所有MoM的乘积;而每年12月的基数效应固定为1.0。
- 举个例子:2020年6月的基数效应 = 2019年7月MoM × 2019年8月MoM × ... × 2019年12月MoM;2020年9月则是2019年10-12月MoM的乘积。
2. 新价格效应(new_price_effect)
- 这个更直观:当年第N个月的新价格效应,就是当年1月到当前月份所有MoM的累积乘积。
- 比如2020年4月的新价格效应 = 2020年1月MoM × 2020年2月MoM × 2020年3月MoM × 2020年4月MoM。
待处理数据
先看我们要处理的原始数据:
data = [{'date': '2020-1-31', 'MoM': 1.014}, {'date': '2020-2-29', 'MoM': 1.008}, {'date': '2020-3-31', 'MoM': 0.988}, {'date': '2020-4-30', 'MoM': 0.991}, {'date': '2020-5-31', 'MoM': 0.992}, {'date': '2020-6-30', 'MoM': 0.999339}, {'date': '2020-7-31', 'MoM': 1.006159}, {'date': '2020-8-31', 'MoM': 1.00401}, {'date': '2020-9-30', 'MoM': 1.002325}, {'date': '2020-10-31', 'MoM': 0.997}, {'date': '2020-11-30', 'MoM': 0.9940000000000001}, {'date': '2020-12-31', 'MoM': 1.0070000000000001}, {'date': '2021-1-31', 'MoM': 1.01}, {'date': '2021-2-28', 'MoM': 1.006}, {'date': '2021-3-31', 'MoM': 0.995}, {'date': '2021-4-30', 'MoM': 0.997}, {'date': '2021-5-31', 'MoM': 0.998}, {'date': '2021-6-30', 'MoM': 0.996}, {'date': '2021-7-31', 'MoM': 1.003}, {'date': '2021-8-31', 'MoM': 1.001}]
Pandas实现步骤
1. 导入库并预处理数据
首先把数据转成DataFrame,同时处理日期,提取年份和月份,方便后续分组和匹配:
import pandas as pd import numpy as np # 转换为DataFrame df = pd.DataFrame(data) # 解析日期格式 df['date'] = pd.to_datetime(df['date']) # 提取年份和月份字段 df['year'] = df['date'].dt.year df['month'] = df['date'].dt.month
2. 计算新价格效应(new_price_effect)
这个很简单,按年份分组后,用cumprod()计算MoM的累积乘积就行:
# 按年份分组,计算当月及之前所有MoM的累积乘积 df['new_price_effect'] = df.groupby('year')['MoM'].cumprod()
3. 计算基数效应(base_effect)
这里需要匹配上一年的对应月份区间,我们可以先把上一年的MoM数据存成字典,然后遍历每一行计算乘积:
# 把(year, month)作为key,MoM作为value,方便快速查询 prev_year_mom_map = df.set_index(['year', 'month'])['MoM'].to_dict() # 初始化基数效应列 df['base_effect'] = np.nan # 遍历每一行计算 for idx, row in df.iterrows(): curr_year = row['year'] curr_month = row['month'] if curr_month == 12: # 每年12月基数效应固定为1.0 df.loc[idx, 'base_effect'] = 1.0 else: # 计算上一年curr_month+1到12月的MoM乘积 product = 1.0 # 遍历需要相乘的月份 for month in range(curr_month + 1, 13): product *= prev_year_mom_map.get((curr_year - 1, month), 1.0) df.loc[idx, 'base_effect'] = product
查看结果
运行完上面的代码后,你可以用下面的代码查看最终结果:
print(df[['date', 'MoM', 'base_effect', 'new_price_effect']].round(6))
比如2021年1月的基数效应,就是2020年2-12月所有MoM的乘积;2021年3月的新价格效应是2021年1-3月MoM的累积乘积,完全符合规则。
内容的提问来源于stack exchange,提问作者ah bon
相关产品推荐
相关产品推荐

