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

如何在Pandas DataFrame中按周分组且分组不跨越月份?

Pandas实现按周分组且周不跨月的方法

核心思路

要实现周分组不跨月,最直接的方式是先按月份拆分数据,在每个月内部生成周区间,确保每个周的起始和结束都落在同一个月内,再对每个月的周进行分组统计,最后补全无数据周的0值。

具体实现步骤

1. 导入数据并预处理

先将日期列转为datetime类型,确保后续日期操作可用:

import pandas as pd

# 示例数据
data = {
    'Date': ['2021-01-15', '2021-01-17', '2021-01-19', '2021-02-04'],
    'Value': [4, 3, 10, 1]
}
df = pd.DataFrame(data)

# 转换日期格式
df['Date'] = pd.to_datetime(df['Date'])

2. 生成所有不跨月的周区间

编写函数遍历每个月份,生成该月内的所有周区间(周起始按周一计算,若周结束超出当月月底则取月底):

def generate_month_weeks(start_date, end_date):
    week_intervals = []
    current_month_start = start_date.replace(day=1)
    while current_month_start <= end_date:
        # 获取当月最后一天
        current_month_end = current_month_start + pd.offsets.MonthEnd(0)
        # 从当月第一天开始生成周区间
        week_start = current_month_start
        while week_start <= current_month_end:
            week_end = week_start + pd.Timedelta(days=6)
            # 周结束不能超过当月月底
            if week_end > current_month_end:
                week_end = current_month_end
            week_intervals.append((week_start, week_end))
            # 下一周起始
            week_start = week_end + pd.Timedelta(days=1)
        # 切换到下一个月
        current_month_start = current_month_start + pd.offsets.MonthBegin(1)
    return week_intervals

# 生成覆盖所有数据月份的周区间
min_date = df['Date'].min().replace(day=1)
max_date = df['Date'].max() + pd.offsets.MonthEnd(0)
all_month_weeks = generate_month_weeks(min_date, max_date)

3. 生成周区间对照表

将周区间转为DataFrame,方便后续匹配:

week_df = pd.DataFrame(all_month_weeks, columns=['Week_Start', 'Week_End'])
week_df['Week'] = week_df['Week_Start'].dt.strftime('%Y-%m-%d') + '-' + week_df['Week_End'].dt.strftime('%Y-%m-%d')

4. 匹配原数据与周区间并分组求和

给原数据的每条记录匹配对应的周区间,再按周分组计算Value的总和:

# 给每个日期匹配对应的周区间
def match_week(date, week_list):
    for start, end in week_list:
        if start <= date <= end:
            return f"{start.strftime('%Y-%m-%d')}-{end.strftime('%Y-%m-%d')}"
    return None

df['Week'] = df['Date'].apply(lambda x: match_week(x, all_month_weeks))

# 按周分组求和
weekly_sum = df.groupby('Week')['Value'].sum().reset_index()

5. 合并结果并补全空周的0值

将所有周区间与分组结果合并,无数据的周填充0:

final_result = pd.merge(week_df[['Week']], weekly_sum, on='Week', how='left').fillna(0)
final_result.rename(columns={'Value': 'Sum_value'}, inplace=True)

print(final_result)

输出示例

运行后会得到包含所有月份周区间的结果,例如:

Week  Sum_value
0  2021-01-01-2021-01-06        0.0
1  2021-01-07-2021-01-13        0.0
2  2021-01-14-2021-01-20       17.0
3  2021-01-21-2021-01-27        0.0
4  2021-01-28-2021-01-31        0.0
5  2021-02-01-2021-02-07        1.0
...

自定义调整

  • 如果需要以周日作为周结束,只需调整week_start的初始值为当月第一个周日,或者修改周区间的计算逻辑即可。
  • 若不需要显示无数据的周,可跳过合并步骤直接使用weekly_sum。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 21:33:16