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

如何按日历周拆分含日期列索引的Pandas DataFrame?

按日历周拆分列索引为日期的Pandas DataFrame

问题描述

现有一个列索引为日期的Pandas DataFrame,需要按周一至周日的日历周拆分为多个子DataFrame。以下是初始化代码及两次尝试的问题:

# Imports
import numpy as np  # version 1.20.3
import pandas as pd  # version 1.3.4  

# Dataframe initialization
np.random.seed(0)
col_idx = pd.date_range(start="2022-12-19", end="2023-01-15", freq="D")
data = np.random.rand(5, len(col_idx))
df = pd.DataFrame(data, columns=col_idx)

尝试01的问题

  • 2023-01-01被单独拆分为子DataFrame,无法归入2022-12-26至2023-01-01的完整周
  • 触发FutureWarning,提示week访问器已被弃用(Pandas 1.3.4版本)

尝试02的问题

使用pd.Grouper(freq="W-MON", axis=1)分组后,生成的子DataFrame包含28列且行数异常,结果不符合预期

正确实现思路及代码

核心思路

  • 使用ISO日历周进行分组:ISO周以周一为起始日、周日为结束日,跨年的周会被归到对应的ISO年份下(例如2023-01-01属于2022年的第52周),完美解决跨年周的拆分问题
  • 用dt.isocalendar()替代弃用的week访问器,获取ISO周的年份和周数,避免警告

代码实现

import numpy as np
import pandas as pd

# 初始化DataFrame(同原代码)
np.random.seed(0)
col_idx = pd.date_range(start="2022-12-19", end="2023-01-15", freq="D")
data = np.random.rand(5, len(col_idx))
df = pd.DataFrame(data, columns=col_idx)

with pd.ExcelWriter("correct_split.xlsx") as writer:
    row_idx = 1
    # 获取列索引的ISO周年份和周数,作为分组键
    iso_weeks = df.columns.to_series().apply(lambda x: (x.isocalendar().year, x.isocalendar().week))
    # 按ISO周分组(axis=1表示按列分组)
    grouper = df.groupby(iso_weeks, axis=1)
    
    for (week_year, week_num), sub_df in grouper:
        # 此处可添加子DataFrame的处理逻辑
        print(f"处理ISO周:{week_year}年第{week_num}周,包含{len(sub_df.columns)}天")
        
        # 写入Excel
        sub_df.to_excel(writer, startrow=row_idx, index=False)
        row_idx += len(sub_df) + 3

代码解释

  1. ISO周分组键:通过x.isocalendar().year和x.isocalendar().week获取每个日期所属的ISO周年份和周数,确保跨年的日期(如2023-01-01)被归入正确的周组
  2. 按列分组:groupby指定axis=1,对列进行分组,得到每个周对应的子DataFrame
  3. Excel写入逻辑:保持原有的行索引累加逻辑,确保每个子DataFrame在Excel中分开显示

另一种实现方式(使用pd.Grouper)

如果偏好使用pd.Grouper,需正确设置频率和周起始日,代码如下:

with pd.ExcelWriter("correct_split_grouper.xlsx") as writer:
    row_idx = 1
    # 设置周频率为"W-SUN"(周日为周结束日,对应周一至周日的周),axis=1表示按列分组
    grouper = df.groupby(pd.Grouper(freq="W-SUN", axis=1))
    
    for week_end, sub_df in grouper:
        # 过滤空的子DataFrame(无对应日期的周)
        if not sub_df.columns.empty:
            print(f"处理周:结束于{week_end.date()},包含{len(sub_df.columns)}天")
            sub_df.to_excel(writer, startrow=row_idx, index=False)
            row_idx += len(sub_df) + 3
  • freq="W-SUN"表示以周日为周的结束日,对应周一至周日的完整周
  • 需过滤空的子DataFrame,因为pd.Grouper会生成覆盖整个时间范围的所有周,包括无数据的周

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 07:10:23