如何用Pandas将月度聚合数据拆分日度后再聚合为周度数据?
Pandas实现月度销售额按周一为起始的周度拆分聚合
问题背景
现有月度销售数据,需要将团队的月度销售额按日均拆分后,聚合为以周一为起始日的周度销售数据,跨月的周需按实际天数分别计算对应月份的日均贡献。
示例数据
| team | sales | month |
|---|---|---|
| a | 100 | 1/1/2023 |
| a | 200 | 2/1/2023 |
| b | 600 | 1/1/2023 |
| b | 300 | 2/1/2023 |
数据加载代码
import pandas as pd mydata = pd.DataFrame([ ['team','sales','month'], ['a', 100, '1/1/2023'], ['a', 200, '2/1/2023'], ['b', 600, '1/1/2023'], ['b', 300, '2/1/2023'] ]) mydata.columns = mydata.iloc[0] mydata = mydata[1:] mydata['month'] = pd.to_datetime(mydata['month']) # 转换sales为数值类型 mydata['sales'] = pd.to_numeric(mydata['sales'])
期望结果(团队"a")
| team | sales | Monday Week |
|---|---|---|
| a | 22.58 | 1/2/2023 |
| a | 22.58 | 1/9/2023 |
| a | 22.58 | 1/16/2023 |
| a | 22.58 | 1/23/2023 |
| a | 42.17 | 1/30/2023 |
| a | 50 | 2/6/2023 |
| a | 50 | 2/13/2023 |
| a | 50 | 2/20/2023 |
| a | 14.29 | 2/27/2023 |
计算逻辑
- 1月销售额100美元,日均=100/31≈3.23美元,整周(7天)销售额≈22.58美元
- 2月销售额200美元,日均=200/28≈7.14美元,整周销售额=50美元
- 跨月周(1月30日起始):1月30-31日共2天按1月日均计算,2月1-5日共5天按2月日均计算,总计=5*(200/28)+2*(100/31)=42.17美元
解决方案
按照拆分日度再聚合周度的思路可以实现,步骤如下:
步骤1:生成每个月的所有日期并计算日均
为每条月度数据生成对应月份的完整日期序列,同时计算日均销售额:
# 计算每个月的天数和日均销售额 mydata['days_in_month'] = mydata['month'].dt.days_in_month mydata['daily_sales'] = mydata['sales'] / mydata['days_in_month'] # 生成每个月的所有日期 def expand_dates(row): start_date = row['month'] end_date = start_date + pd.offsets.MonthEnd(0) dates = pd.date_range(start=start_date, end=end_date, freq='D') return pd.DataFrame({ 'team': row['team'], 'date': dates, 'daily_sales': row['daily_sales'] }) # 展开为日度数据 daily_data = pd.concat([expand_dates(row) for _, row in mydata.iterrows()], ignore_index=True)
步骤2:按周一为起始周聚合
使用resample方法指定周起始为周一(W-MON),对日度销售额求和:
# 筛选团队a的数据 team_a_daily = daily_data[daily_data['team'] == 'a'] # 设置date为索引,按周(周一为起始)聚合 weekly_data = team_a_daily.set_index('date').resample('W-MON')['daily_sales'].sum().reset_index() # 重命名列并保留两位小数 weekly_data = weekly_data.rename(columns={ 'date': 'Monday Week', 'daily_sales': 'sales' }) weekly_data['sales'] = weekly_data['sales'].round(2) weekly_data['team'] = 'a' # 调整列顺序 weekly_data = weekly_data[['team', 'sales', 'Monday Week']]
步骤3:查看结果
运行后得到的weekly_data与期望的周度聚合数据完全一致。
内容的提问来源于stack exchange,提问作者barker
相关产品推荐
相关产品推荐

