You need to enable JavaScript to run this app. Pandas中结合groupby与cumsum实现按类别、年、月维度的累计值计算
优惠活动
大模型
产品
解决方案
定价
更多

Pandas中结合groupby与cumsum实现按类别、年、月维度的累计值计算

问题核心偏差

你之前的cumsum计算逻辑存在两个关键误区,导致结果不符合预期:

  • 分组维度完全错位:对已经按年-月-类聚合好的单条计数记录,重复使用同三个字段做groupby,每个分组内仅1条数据,cumsum没有累加空间
  • 缺少全量时间框架:默认分组逻辑只会保留有原始数据的年-月-类组合,缺失的月份不会自动补全,也无法实现“无数据月份沿用前序累计值”的要求
正确实现步骤

1. 完成基础计数聚合(原有逻辑正确)

先拿到每个存在数据的年-月-类别的原始记录数:

import pandas as pd

sample = [
    {'name':11,'category':'A','year':2017,'month':1},
    {'name':22,'category':'A','year':2017,'month':2},
    {'name':33,'category':'B','year':2015,'month':1},
    {'name':33,'category':'C','year':2017,'month':3},
    {'name':33,'category':'B','year':2017,'month':8},
    {'name':44,'category':'B','year':2016,'month':4},
    {'name':44,'category':'A','year':2017,'month':6},
    {'name':55,'category':'C','year':2016,'month':9},
    {'name':55,'category':'C','year':2017,'month':5},
    {'name':55,'category':'B','year':2017,'month':11}
]
sample_df = pd.DataFrame(sample)

# 基础聚合:统计每个年-月-类别的原始计数
sample_counts = sample_df.groupby(['year','month','category']).agg(
    category_count=('category', 'count')
).reset_index()

2. 生成全量年-月-类别网格

为了覆盖每个年度下1-12月的全量范围,先通过笛卡尔积生成所有需要的维度组合,避免月份缺失:

# 提取所有需要覆盖的维度
all_years = sample_counts['year'].unique()
all_categories = sample_counts['category'].unique()
all_months = range(1, 13)

# 生成全量框架:年份 × 月份(1-12) × 类别
full_grid = pd.MultiIndex.from_product(
    iterables=[all_years, all_months, all_categories],
    names=['year', 'month', 'category']
).to_frame(index=False)

3. 匹配原始计数到全量框架

把有数据的计数匹配到全量框架上,无数据的位置填充0:

merged = full_grid.merge(
    sample_counts,
    on=['year', 'month', 'category'],
    how='left'
).fillna({'category_count': 0})

4. 计算累计值

按照时间推进的顺序排序后,以「年+类别」为分组单位做累计求和(完全匹配你给出的示例输出逻辑):

# 按年份、类别、月份升序排序,保证时间顺序正确
merged = merged.sort_values(['year', 'category', 'month'])

# 核心:同一年、同一类别下,按月份累加计数
merged['Cumulative_By_Category'] = merged.groupby(
    ['year', 'category']
)['category_count'].cumsum()

适配不同需求的调整:如果需要做跨年度全局累计(也就是2017年1月的累计值需要包含2015、2016年该类别的所有计数),只需要把cumsum的分组键改为仅['category']即可,无需其他调整。

5. 整理为目标输出格式

调整列名和顺序,匹配你要求的输出结构:

result = merged.rename(
    columns={'category': 'Category', 'month': 'Month', 'year': 'Year'}
)[['Category', 'Month', 'Year', 'Cumulative_By_Category']]

result = result.sort_values(['Year', 'Category', 'Month']).reset_index(drop=True)

以上代码运行后,2017年的输出结果和你给出的示例完全一致,会自动补全所有缺失月份、保持无数据月份的累计值连续不跳变。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 09:54:06