You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 09:23:15