You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Pandas时间序列:基于day-of-week的跨年度pct_change通用方案问询

按星期几匹配前一年首个对应日期的同比百分比变化计算

这需求挺实用的——不是死板地按同月同日同比,而是按星期几对齐前一年的首个对应日期,咱们一步步来实现通用方案。

核心思路拆解

要实现这个需求,关键是给每个日期找到前一年中第一个和它星期几相同的日期,再计算当前值与该日期值的百分比变化。具体分四步:

  1. 给原数据标记年份和星期几
  2. 预计算每一年对应的前一年中,每个星期几的首个日期
  3. 将原数据与预计算的匹配日期关联,获取对应年份的基准值
  4. 计算同比百分比变化

完整代码实现

1. 生成测试数据

首先用你提供的测试数据初始化:

import pandas as pd
import numpy as np

# 生成datetime索引的DataFrame
idx = pd.date_range('2019-01-01', periods=1000)
df = pd.DataFrame(np.arange(1000), index=idx, columns=['value'])

2. 标记年份和星期几

给DataFrame添加辅助列,方便后续分组匹配:

df['year'] = df.index.year
df['dow'] = df.index.dayofweek  # pandas中0=周一,6=周日

3. 预计算前一年的星期几首个日期

创建一个字典,存储每个年份对应的前一年中,每个星期几的第一个日期:

# 获取所有涉及的年份
years = df['year'].unique()
prev_year_dow_mapping = {}

for year in years:
    prev_year = year - 1
    # 生成前一年的完整日期范围
    prev_year_dates = pd.date_range(start=f"{prev_year}-01-01", end=f"{prev_year}-12-31")
    # 按星期几分组,取每个组的第一个日期
    prev_year_dow_mapping[year] = (
        prev_year_dates.to_series(name="match_date")
        .groupby(prev_year_dates.dayofweek)
        .first()
    )

4. 关联匹配日期并计算同比

这里推荐用merge的方式(比apply高效得多,适合大数据量):

# 把预计算的映射转换成DataFrame,方便合并
prev_year_dows_df = []
for year, dow_map in prev_year_dow_mapping.items():
    temp_df = dow_map.reset_index().rename(columns={"index": "dow"})
    temp_df['year'] = year
    prev_year_dows_df.append(temp_df)
prev_year_dows_df = pd.concat(prev_year_dows_df)

# 合并原数据与匹配日期
df_merged = df.merge(prev_year_dows_df, on=['year', 'dow'], how='left')

# 通过匹配日期获取前一年的基准值
df_merged['prev_year_value'] = df_merged['match_date'].map(df['value'])

# 计算同比百分比变化
df_merged['pct_change'] = (df_merged['value'] - df_merged['prev_year_value']) / df_merged['prev_year_value']

验证你的例子

拿你提到的2020-01-01来验证:

  • 2020-01-01是周三(dow=2),2019年第一个周三是2019-01-02
  • 2020-01-01的value是365(因为2019年有365天,从0开始计数),2019-01-02的value是1
  • 计算得到的pct_change(365-1)/1 = 364,也就是36400%,完全符合你的预期

通用场景适配

这个方案自动处理平年/闰年的差异,不管目标年份是平年还是闰年,都会准确找到前一年中对应星期几的首个日期,适用于任意连续年份的时间序列数据。

内容的提问来源于stack exchange,提问作者FooBar

火山引擎 最新活动