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

如何在Pandas中计算含部分数据的月度YoY同比变化?

修正部分月度数据的YoY同比计算逻辑

核心思路

放弃直接用月度重采样总和做同比的方式,转而基于日度数据匹配时间长度完全一致的周期:当前不完整月份已统计N天,就取去年同期同一月份的前N天数据做对比,确保两个统计窗口的时间范围对等,避免失真。

具体实现步骤

假设你的日度数据DataFrame为df,日期列是date,目标统计列是customer_count:

  1. 锁定当前不完整月份的时间范围

    # 获取最新一条数据的日期
    latest_date = df['date'].max()
    # 确定当前不完整月份的第一天
    current_month_start = latest_date.replace(day=1)
    # 计算当前月份已统计的天数
    days_in_current = (latest_date - current_month_start).days + 1
    
  2. 匹配去年同期的对应时间范围

    # 去年同期月份的第一天
    last_year_month_start = current_month_start.replace(year=current_month_start.year - 1)
    # 去年同期对应结束日期(和今年统计天数一致)
    last_year_end = last_year_month_start + pd.Timedelta(days=days_in_current - 1)
    
  3. 计算两个周期的累计值

    # 今年部分月份的累计客户数
    current_total = df[(df['date'] >= current_month_start) & (df['date'] <= latest_date)]['customer_count'].sum()
    # 去年同期对应天数的累计客户数
    last_year_total = df[(df['date'] >= last_year_month_start) & (df['date'] <= last_year_end)]['customer_count'].sum()
    
  4. 计算同比变化率

    # 处理除数为0的边界情况
    if last_year_total != 0:
        yoy_change = (current_total - last_year_total) / last_year_total * 100
    else:
        yoy_change = None  # 可根据业务需求替换为0或其他默认值
    print(f"当前部分月度客户数同比变化: {yoy_change:.1f}%")
    

批量处理所有月份(含完整/部分)

如果要对所有月份统一计算,自动区分完整月份和最后一个不完整月份,可以用分组+自定义函数实现:

def calculate_yoy(group):
    group_max_date = group['date'].max()
    group_month_start = group_max_date.replace(day=1)
    # 判断是否为完整月份
    is_full_month = (group_month_start + pd.offsets.MonthEnd(0)) == group_max_date
    
    if is_full_month:
        # 完整月份用常规月度同比
        last_year_group = df[(df['date'].dt.year == group_month_start.year - 1) & 
                             (df['date'].dt.month == group_month_start.month)]
        last_year_total = last_year_group['customer_count'].sum()
    else:
        # 部分月份取同期对应天数
        days_in_current = (group_max_date - group_month_start).days + 1
        last_year_month_start = group_month_start.replace(year=group_month_start.year - 1)
        last_year_end = last_year_month_start + pd.Timedelta(days=days_in_current - 1)
        last_year_group = df[(df['date'] >= last_year_month_start) & (df['date'] <= last_year_end)]
        last_year_total = last_year_group['customer_count'].sum()
    
    current_total = group['customer_count'].sum()
    return (current_total - last_year_total) / last_year_total * 100 if last_year_total != 0 else None

# 按月份分组计算同比
df['month'] = df['date'].dt.to_period('M')
yoy_results = df.groupby('month').apply(calculate_yoy).rename('yoy_change')

关键说明

  • 核心是确保对比窗口的时间长度完全一致,从根源上解决部分月份和完整月份直接对比的失真问题。
  • 若业务需要统计均值而非总和,只需将代码中的sum()替换为mean()即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 06:11:04