如何基于周二起始的自定义周对DataFrame执行Groupby聚合?
解决方案
步骤1:合并日期列并转换为datetime类型
首先需要把Year、Month、Day三列合并成标准datetime列,这是时间分组的基础操作:
import pandas as pd # 假设你的DataFrame名为df df['date'] = pd.to_datetime(df[['Year', 'Month', 'Day']])
步骤2:生成以周二为起始的自定义周分组键
以你指定的第一周起始日(2022年8月31日,周二)为基准,计算每个日期对应的周编号:
# 设置基准起始周二 base_tuesday = pd.to_datetime('2022-08-31') # 计算日期与基准日的天数差,整除7得到周分组编号(0对应第一周,1对应第二周,以此类推) df['custom_week'] = ((df['date'] - base_tuesday).dt.days // 7) # 生成可读性更强的周标签(如"周1"、"周2") df['custom_week_label'] = '周' + (df['custom_week'] + 1).astype(str)
如果你的数据需要覆盖2021年8月31日(也是周二)及更早日期,只需将base_tuesday改为pd.to_datetime('2021-08-31')即可。
步骤3:按自定义周分组并求和
根据需求选择对应的分组求和方式:
场景1:按周汇总所有日期的Time列总和
weekly_total = df.groupby('custom_week_label')[['Time1', 'Time2', 'Time3']].sum().reset_index()
场景2:保留每日数据,同时标记所属周(得到每日Time列求和并按周分组展示)
daily_weekly_total = df.groupby(['custom_week_label', 'date'])[['Time1', 'Time2', 'Time3']].sum().reset_index()
步骤4:自定义周范围标签(可选)
如果需要在结果中显示每周的起止日期,可以添加以下代码:
# 计算每个周的起止日期 week_ranges = df.groupby('custom_week')['date'].agg(['min', 'max']) week_ranges['week_range'] = week_ranges['min'].dt.strftime('%Y-%m-%d') + ' 至 ' + week_ranges['max'].dt.strftime('%Y-%m-%d') # 合并到求和结果中 weekly_total = weekly_total.merge(week_ranges[['week_range']], left_on='custom_week', right_index=True)
完整示例代码
import pandas as pd # 模拟符合需求的测试数据 data = { 'Year': [2022]*6 + [2022]*6, 'Month': [8]*3 + [9]*3 + [9]*3 + [10]*3, 'Day': [31, 1, 2, 3, 4, 5, 6,7,8,9,10,11], 'Time1': [1,2,3,4,5,6,7,8,9,10,11,12], 'Time2': [2,3,4,5,6,7,8,9,10,11,12,13], 'Time3': [3,4,5,6,7,8,9,10,11,12,13,14] } df = pd.DataFrame(data) # 合并日期列 df['date'] = pd.to_datetime(df[['Year', 'Month', 'Day']]) # 生成自定义周分组键 base_tuesday = pd.to_datetime('2022-08-31') df['custom_week'] = ((df['date'] - base_tuesday).dt.days // 7) df['custom_week_label'] = '周' + (df['custom_week'] + 1).astype(str) # 按周+日期分组求和 daily_weekly_total = df.groupby(['custom_week_label', 'date'])[['Time1', 'Time2', 'Time3']].sum().reset_index() print(daily_weekly_total)
输出示例:
| custom_week_label | date | Time1 | Time2 | Time3 |
|---|---|---|---|---|
| 周1 | 2022-08-31 | 1 | 2 | 3 |
| 周1 | 2022-09-01 | 2 | 3 | 4 |
| 周1 | 2022-09-02 | 3 | 4 | 5 |
| 周1 | 2022-09-03 | 4 | 5 | 6 |
| 周1 | 2022-09-04 | 5 | 6 | 7 |
| 周1 | 2022-09-05 | 6 | 7 | 8 |
| 周2 | 2022-09-06 | 7 | 8 | 9 |
| ... | ... | ... | ... | ... |
内容的提问来源于stack exchange,提问作者Alejandra
相关产品推荐
相关产品推荐

