如何在Pandas中实现同日期跨年度的pct_change计算?
解决按年同月同日计算百分比变化的问题
嘿,这个问题我之前处理过,pct_change(freq='Y')在碰到闰年的时候确实容易踩坑——因为2月29日的存在会导致索引匹配出问题,直接触发ValueError。这里给你两个靠谱的解决方案,都能满足你的需求,还能自动忽略2月29日:
方法一:手动匹配前一年日期(灵活可控)
这个方法的思路是先过滤掉2月29日的数据,然后为每一行生成前一年的对应日期,再通过映射找到对应的值,最后计算同比变化:
import pandas as pd import numpy as np # 生成示例数据 idx = pd.date_range('2000-01-01', periods=1000) df = pd.DataFrame(np.arange(1000), index=idx, columns=['value']) # 第一步:过滤掉所有2月29日的行 df = df[~((df.index.month == 2) & (df.index.day == 29))] # 第二步:为每个日期生成前一年的对应日期 df['prev_year_date'] = df.index - pd.DateOffset(years=1) # 第三步:映射前一年的值,计算同比百分比变化 df['prev_year_value'] = df['prev_year_date'].map(df['value']) df['year_over_year_pct'] = (df['value'] - df['prev_year_value']) / df['prev_year_value'] # 查看预期结果 print(df.loc['2001-01-01':'2001-01-02'])
运行后你会看到:
- 2000年的所有行对应的
year_over_year_pct都是NaN(因为没有前一年数据) - 2001-01-01的结果是
inf(因为前一年值为0,除法无意义) - 2001-01-02的结果是366.0,完全符合你的预期
方法二:分组+pct_change(简洁高效)
这个方法利用groupby按「月-日」分组,每个分组内都是不同年份的同一天数据,直接用pct_change计算即可:
import pandas as pd import numpy as np # 生成示例数据 idx = pd.date_range('2000-01-01', periods=1000) df = pd.DataFrame(np.arange(1000), index=idx, columns=['value']) # 过滤2月29日数据 df = df[~((df.index.month == 2) & (df.index.day == 29))] # 提取「月-日」作为分组键,比如"01-01" df['month_day'] = df.index.strftime('%m-%d') # 按「月-日」分组,对每个分组内的数据按年份顺序计算同比变化 df['year_over_year_pct'] = df.groupby('month_day')['value'].pct_change(periods=1) # 查看预期结果 print(df.loc['2001-01-01':'2001-01-02'])
这个方法更简洁,因为每个「月-日」分组内的数据天然按年份排序,pct_change(periods=1)直接取前一年的值计算变化率,结果和方法一完全一致。
为什么原方法会报错?
df.pct_change(freq='Y')的底层是按年度频率偏移索引后对齐数据,但如果原数据包含闰年的2月29日,偏移一年后(非闰年)没有对应的日期,会导致索引对齐时出现重复或缺失,最终触发ValueError: cannot reindex from a duplicate axis。所以先过滤2月29日是解决问题的前提。
内容的提问来源于stack exchange,提问作者FooBar
相关产品推荐
相关产品推荐

