Python中基于月内周数重组周数据生成报表月份列
解决周度数据按每月第3个周六分组并生成报表日期列的问题
错误原因分析
你遇到的TypeError: Series.replace() got an unexpected keyword argument 'day'是因为pandas.Series.replace()方法没有day参数——参考的方案里的replace(day=...)是针对单个datetime对象的操作,不能直接套用在Series上。要对Series中的datetime元素修改,需使用Series的datetime访问器方法dt.replace()。
完整解决方案
以下是实现需求的代码,包含数据类型转换、报表截止日计算、分组匹配报表日期的完整流程:
1. 导入依赖并初始化数据
import pandas as pd from dateutil.relativedelta import relativedelta from dateutil.rrule import rrule, WEEKLY, SA # 初始化示例数据 df = pd.DataFrame({ 'Time Entry Week':['2022-12-11','2022-12-18','2022-12-25','2023-01-01','2023-01-08','2023-01-15','2023-01-22'], 'Time Period':['12/11/2022 - 12/17/2022','12/18/2022 - 12/24/2022','12/25/2022 - 12/31/2022','01/01/2023 - 01/07/2023','01/08/2023 - 01/14/2023','01/15/2023 - 01/21/2023','01/22/2023 - 01/28/2023'] })
2. 提取周结束日期并转换为datetime类型
从Time Period中提取每周的结束日期,作为分组判断的核心依据:
# 提取Time Period中的结束日期并转为datetime类型 df['Week End Date'] = pd.to_datetime(df['Time Period'].str.split(' - ').str[1]) # 同时将Time Entry Week转为datetime类型 df['Time Entry Week'] = pd.to_datetime(df['Time Entry Week'])
3. 生成所有报表截止日(每月第3个周六)
生成覆盖数据时间范围的所有报表截止日,用于后续匹配分组:
# 获取数据的最小、最大日期,确定报表范围边界 min_date = df['Week End Date'].min() max_date = df['Week End Date'].max() # 生成每月第3个周六的截止日列表 report_cutoffs = list(rrule( WEEKLY, byweekday=SA, # 指定周六 count=3, # 取每月第3个 dtstart=min_date.replace(day=1) - relativedelta(months=1), until=max_date.replace(day=1) + relativedelta(months=1) )) # 去重并排序,避免重复生成同一月份的截止日 report_cutoffs = sorted(list(set(report_cutoffs)))
4. 匹配每条周数据对应的报表日期
根据周结束日期所在的报表周期,分配对应的报表年月:
def get_report_date(week_end): # 逻辑:周结束日期<=某报表截止日时,归为该截止日所在月份的报表 for cutoff in report_cutoffs: if week_end <= cutoff: return cutoff.strftime('%Y-%m') # 处理超出预设范围的极端情况 return max_date.strftime('%Y-%m') # 新增Report Date列 df['Report Date'] = df['Week End Date'].apply(get_report_date)
5. 最终结果整理
可删除中间辅助列,得到目标表格:
# 可选:删除辅助列Week End Date df = df.drop('Week End Date', axis=1) print(df)
运行后输出结果符合需求:
| Time Entry Week | Time Period | Report Date |
|---|---|---|
| 2022-12-11 | 12/11/2022 - 12/17/2022 | 2022-12 |
| 2022-12-18 | 12/18/2022 - 12/24/2022 | 2023-01 |
| 2022-12-25 | 12/25/2022 - 12/31/2022 | 2023-01 |
| 2023-01-01 | 01/01/2023 - 01/07/2023 | 2023-01 |
| 2023-01-08 | 01/08/2023 - 01/14/2023 | 2023-01 |
| 2023-01-15 | 01/15/2023 - 01/21/2023 | 2023-01 |
| 2023-01-22 | 01/22/2023 - 01/28/2023 | 2023-02 |
关键说明
- 解决
replace错误的核心:对datetime类型的Series操作,必须用dt.replace();仅单个datetime对象可直接调用datetime.replace(day=...)。 - 报表分组逻辑:每周数据的结束日期落在「上一报表截止日之后,当前报表截止日之前(含)」区间内时,归为当前报表截止日所在月份的报表。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

