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

Pandas如何实现非常规groupby:年末日期同时归属相邻两个年度分组

实现方案

针对大体量DataFrame场景,采用pandas原生矢量化操作实现,全程无循环、无逐行遍历,性能开销极低。核心逻辑:每年仅需额外复制1条12月最后一个可见日期的记录,将其分组标记设为下一年,即可满足规则要求,不需要构建样例中占内存的稀疏宽表(样例中g1~g6仅为效果展示,实际分组计算无需生成这类列)。

实现逻辑

  • 先将date列转换为pandas datetime类型,为后续日期计算提速
  • 为每条记录添加基础分组标记:即日期对应的自然年
  • 按自然年分组,筛选出每年12月的最大日期(即每年12月最后一个可见的观测日)
  • 将筛选出的年末日期记录复制一份,分组标记改为对应年份+1
  • 把原数据集和复制出的追加记录合并,直接按分组标记做groupby即可,完全符合规则要求

可直接运行的代码

import pandas as pd

# 加载样例数据
data = {'date': ['2017-03-31', '2017-04-03', '2017-12-27', '2017-12-28',
                 '2017-12-29', '2018-01-02', '2018-12-31', '2019-01-02',
                 '2019-01-03', '2019-12-31', '2020-12-30', '2020-12-31',
                 '2021-01-20', '2021-12-30', '2021-12-31', '2022-05-30',
                 '2022-05-31'] 
       }
df = pd.DataFrame(data)
# 转换日期格式
df['date'] = pd.to_datetime(df['date'])
# 生成基础分组年份:日期本身所属自然年
df['group_year'] = df['date'].dt.year

# 提取每年12月的最后一个可见日期
dec_last_dates = (
    df[df['date'].dt.month == 12]  # 筛选所有12月的记录
    .groupby(df['date'].dt.year)['date']
    .max()  # 取每年12月的最大日期,即最后一个观测日
    .reset_index(drop=True)
    .to_frame()
)
# 给年末日期副本设置分组年份为下一年
dec_last_dates['group_year'] = dec_last_dates['date'].dt.year + 1

# 合并原数据与追加的年末副本,即可直接用于分组计算
df_for_calc = pd.concat([df, dec_last_dates], ignore_index=True)

效果验证

如果需要复现样例中的宽表展示效果,对计算用表做一次透视即可,结果和给出的期望分组完全一致:

# 生成样例式宽表
show_result = (
    df_for_calc.assign(val=1)
    .pivot(index='date', columns='group_year', values='val')
    .fillna('')
    .sort_index()
)
# 列名对齐样例的g1~g6格式
show_result.columns = [f'g{i+1}' for i in range(len(show_result.columns))]
print(show_result)

运行后可以看到:每年12月的最后一个可见日期会同时归属当年和下一年分组,其余日期仅归属自身自然年分组,和需求完全匹配。

该方案对千万级以上大体量数据友好度极高:无论时间跨度多长,每年仅新增1条记录,全程矢量化运算没有逐行判断的性能损耗,相比循环、apply类方法效率高出1~2个数量级,内存占用几乎无增长。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 09:57:32