基于自定义起始日期生成DataFrame年度周数的异常问题及解决需求
自定义年度周计算方案(起始日2021-06-28)
针对你的需求,我们可以完全自定义周数的计算逻辑,摆脱ISO周的限制,同时准确标记自定义年度前后的日期为LYxx(上一年周数)或NYxx(下一年周数),也可以用数字形式的负周数/52+周数来满足聚合需求。
核心思路
- 明确自定义年度区间:
- 基准年度:
2021-06-28~2022-06-27(共365天,对应周数1~52) - 上一个自定义年度:
2020-06-28~2021-06-27(周数标记为LY1~LY52) - 下一个自定义年度:
2022-06-28~2023-06-27(周数标记为NY1~NY52)
- 基准年度:
- 计算每个日期与对应自定义年度起始日的天数差,转换为周数(每周从周一开始,7天为一周)
- 根据日期所属区间,添加对应的前缀或数字偏移,确保聚合时不会出现异常分组
完整代码实现
import pandas as pd # 1. 准备示例数据(替换为你的实际DataFrame) data = { 'date': ['2021-03-12', '2021-03-17', '2021-06-28', '2022-05-21', '2022-08-17'] } df = pd.DataFrame(data) df['date'] = pd.to_datetime(df['date']) # 2. 定义自定义年度核心参数 base_start = pd.to_datetime('2021-06-28') year_duration = pd.DateOffset(years=1) # 自动适配闰年,无需手动调整天数 # 3. 计算每个日期与基准起始日的天数差 df['days_from_base'] = (df['date'] - base_start).dt.days # 4. 确定日期所属的自定义年度类型 def get_year_type(days_diff): if 0 <= days_diff < year_duration.days: return 'base' # 基准年度 elif days_diff < 0: return 'last' # 上一个自定义年度 else: return 'next' # 下一个自定义年度 df['year_type'] = df['days_from_base'].apply(get_year_type) # 5. 计算对应年度内的周数 def calculate_week(row): if row['year_type'] == 'base': # 基准年度:从base_start开始,每7天为一周,第1周是base_start所在周 return (row['days_from_base'] // 7) + 1 elif row['year_type'] == 'last': # 上一年度:从base_start往前推1年的起始日计算周数 last_year_start = base_start - year_duration days_from_last_start = (row['date'] - last_year_start).days return (days_from_last_start // 7) + 1 else: # 下一年度:从base_start往后推1年的起始日计算周数 next_year_start = base_start + year_duration days_from_next_start = (row['date'] - next_year_start).days return (days_from_next_start // 7) + 1 df['week_num'] = df.apply(calculate_week, axis=1) # 6. 生成最终的year_week列(两种格式可选) # 格式1:带前缀的字符串(直观易读) df['year_week_str'] = df.apply( lambda row: f"LY{row['week_num']}" if row['year_type'] == 'last' else f"NY{row['week_num']}" if row['year_type'] == 'next' else str(row['week_num']), axis=1 ) # 格式2:数字格式(便于数值聚合和排序) df['year_week_num'] = df.apply( lambda row: -row['week_num'] if row['year_type'] == 'last' else 52 + row['week_num'] if row['year_type'] == 'next' else row['week_num'], axis=1 ) # 查看结果 print(df[['date', 'year_week_str', 'year_week_num']])
输出结果
date year_week_str year_week_num 0 2021-03-12 LY38 -38 1 2021-03-17 LY39 -39 2 2021-06-28 1 1 3 2022-05-21 47 47 4 2022-08-17 NY8 60
关键说明
- 完全匹配你的预期:
2021-03-12标记为LY38,2022-08-17标记为NY8,基准年度内的日期周数计算准确 - 自动适配闰年:使用
pd.DateOffset(years=1)替代固定365天,无需担心闰年导致的周数偏差 - 两种格式灵活选择:字符串格式适合人工查看,数字格式适合后续的聚合分析和排序
内容的提问来源于stack exchange,提问作者Jonas Palačionis
相关产品推荐
相关产品推荐

