Pandas如何实现按月分组累计计数 跨月自动重置计数
问题根源
现有自定义累计函数对全表size列做全局累加,未按「编码+所属月份」维度做分组截断,因此跨月时计数不会从1重新开始。
修正方案
不用自定义累计函数,直接用pandas原生的分组累计方法即可,逻辑更简洁、运行效率更高:
- 如果要保留当前先按天聚合统计每日记录数的逻辑,在聚合结果上按月分组累加:
import pandas as pd # 复用之前生成df_2的逻辑 dict_1 = {"Code" : ['A', 'A', 'A', 'A', 'A', 'A'], 'Period' : ['2022-04-29','2022-04-29', '2022-04-30', '2022-05-01', '2022-05-01', '2022-05-01']} df_1 = pd.DataFrame(dict_1) df_1['Period'] = pd.to_datetime(df_1['Period']).dt.strftime("%Y-%m-%d") df_2 = df_1.groupby(['Period', 'Code'], as_index=False).size() # 新增年月分组键,YYYY-MM-DD格式直接截前7位即可得到年月,无需转datetime效率更高 df_2['year_month'] = df_2['Period'].str[:7] # 按Code、年月分组做累计求和 df_2['Count'] = df_2.groupby(['Code', 'year_month'])['size'].cumsum() # 删除临时列 df_2 = df_2.drop(columns='year_month')
运行后得到的结果完全符合预期:
| Code | Period | size | Count |
|---|---|---|---|
| A | 2022-04-29 | 2 | 2 |
| A | 2022-04-30 | 1 | 3 |
| A | 2022-05-01 | 3 | 3 |
- 如果不需要先按天聚合,要直接在原始明细表上逐行生成跨月重置的累计序号,可以用更简单的写法:
df_1['year_month'] = df_1['Period'].str[:7] # cumcount()从0开始计数,+1后就是从1开始的累计序号 df_1['row_count'] = df_1.groupby(['Code', 'year_month']).cumcount() + 1
运行后逐行结果如下:
| Code | Period | row_count |
|---|---|---|
| A | 2022-04-29 | 1 |
| A | 2022-04-29 | 2 |
| A | 2022-04-30 | 3 |
| A | 2022-05-01 | 1 |
| A | 2022-05-01 | 2 |
| A | 2022-05-01 | 3 |
注意点
- 分组键必须带上
Code字段,否则后续出现B、C等其他编码的数据时,会把不同编码的记录混在一起累计。 - 提取年月时如果已经确定
Period是YYYY-MM-DD格式的字符串,直接用字符串切片取前7位比转datetime类型运算效率更高。
内容的提问来源于stack exchange,提问作者Data-7scientist
相关产品推荐
相关产品推荐

