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

如何用Pandas计算周度数据X列的同比变化(适配52/53周)

周频数据同比变化率计算(适配52/53周年份)

要解决周频数据的同比计算问题,核心是精准匹配「今年同一ISO周次」与「去年同一ISO周次」的数据——普通周数计算可能存在跨年错位,而ISO周是国际标准,能正确区分每年52/53周的情况。以下是具体实现步骤:

关键前提

假设你的数据框df包含:

  • 日期列date(已转为datetime类型)
  • 需要计算同比的数值列x1、x2、x3

步骤1:提取ISO年份与周次

ISO周规则:每年最多53周,周一是一周起始,部分跨年日期(如12月31日)可能归属下一年的第1周,这能保证同周次的业务一致性。

import pandas as pd

# 提取ISO年份和周数
df['iso_year'] = df['date'].dt.isocalendar().year
df['iso_week'] = df['date'].dt.isocalendar().week

步骤2:匹配去年同周数据(两种实现方式)

方式一:Merge自连接(直观易验证)

复制一份去年的数据,将年份加1后与原数据按「ISO年份+ISO周次」合并,确保每一行都匹配到去年同周的数值:

# 复制并处理去年数据
df_prev = df.copy()
df_prev['iso_year'] += 1  # 去年年份+1,对应今年的年份
df_prev = df_prev[['iso_year', 'iso_week', 'x1', 'x2', 'x3']].rename(
    columns={'x1': 'x1_prev', 'x2': 'x2_prev', 'x3': 'x3_prev'}
)

# 合并原数据与去年同周数据
df_merged = pd.merge(df, df_prev, on=['iso_year', 'iso_week'], how='left')

方式二:Groupby分组计算(简洁高效)

按ISO周次分组,在每个组内按年份排序后计算同比变化率:

# 先按周次、年份排序
df = df.sort_values(['iso_week', 'iso_year'])

# 每个周次组内计算同比(periods=1表示取上一年的数据)
for col in ['x1', 'x2', 'x3']:
    df[f'{col}_yoy'] = df.groupby('iso_week')[col].pct_change(periods=1) * 100

步骤3:计算同比变化率

同比公式为:(今年值 - 去年值) / 去年值 * 100(百分比形式),如果用Merge方式,代码如下:

# 批量计算所有X列的同比
for col in ['x1', 'x2', 'x3']:
    df_merged[f'{col}_yoy'] = (df_merged[col] - df_merged[f'{col}_prev']) / df_merged[f'{col}_prev'] * 100

# 保留核心列(可选)
result = df_merged[['date', 'x1', 'x2', 'x3', 'x1_yoy', 'x2_yoy', 'x3_yoy']]

处理53周的特殊情况

如果某一年存在第53周,但去年没有对应周次,匹配后去年的数值会是NaN,同比结果也会是NaN。你可以根据业务需求处理:

  • 删除缺失行:result = result.dropna(subset=['x1_yoy', 'x2_yoy', 'x3_yoy'])
  • 用前一周同比填充:result[['x1_yoy', 'x2_yoy', 'x3_yoy']] = result[['x1_yoy', 'x2_yoy', 'x3_yoy']].fillna(method='ffill')
  • 忽略该周数据:直接保留NaN,后续分析时排除

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 09:11:59