Pandas实现:查找每月第一个周一后的首个周五
查找每月第一个周一之后的首个周五(Pandas实现问题)
问题描述
尝试用Pandas实现查找每月第一个周一之后的首个周五的功能,现有代码无返回结果:
df[(df.index.day_of_week==0) & (df.index.day<15) & (df.shift(-4).index.day_of_week==4)]
数据结构示例(已添加day_of_week列,0=周一,4=周五):
close day_of_week date 2022-07-01 3825.330078 4 2022-07-05 3831.389893 1 2022-07-06 3845.080078 2 2022-07-07 3902.620117 3 2022-07-08 3899.379883 4 2022-07-11 3854.429932 0 2022-07-12 3818.800049 1 2022-07-13 3801.780029 2 2022-07-14 3790.379883 3 2022-07-15 3863.159912 4 ... 2022-08-01 4118.629883 0 2022-08-02 4091.189941 1 2022-08-03 4155.169922 2 2022-08-04 4151.939941 3 2022-08-05 4145.189941 4 ... 2022-09-01 3966.850098 3 2022-09-02 3924.260010 4 2022-09-06 3908.189941 1 2022-09-07 3979.870117 2 2022-09-08 4006.179932 3 2022-09-09 4067.360107 4 2022-09-12 4110.410156 0 2022-09-13 3932.689941 1 2022-09-14 3946.010010 2 2022-09-15 3901.350098 3 2022-09-16 3873.330078 4 ...
期望结果:
2022-07-15 3863.159912 4 2022-08-05 4145.189941 4 2022-09-16 3873.330078 4 2022-10-07 3639.659912 4
补充疑问:现有代码无返回,是否是筛选时不支持shift操作?
问题分析
代码失效不是因为shift不支持,而是逻辑错误:
df.shift(-4)只会移动数据行,索引不会改变,所以df.shift(-4).index.day_of_week和原索引的day_of_week完全一致,这部分条件永远不成立,导致无结果。- 直接用固定天数偏移忽略了非交易日缺失的情况(比如7月2-4日是周末,数据中无记录),无法对应正确日期。
解决方案
步骤说明
- 筛选所有周一,按月份分组取每月第一个周一
- 对每个第一个周一,找到之后(含当周)的首个周五
- 从原数据中提取这些周五的记录
代码实现
import pandas as pd # 确保索引为datetime类型 df.index = pd.to_datetime(df.index) # 1. 获取每月第一个周一的日期 first_mondays = df[df['day_of_week'] == 0].groupby([df.index.year, df.index.month]).first() first_monday_dates = first_mondays.index.to_list() # 转换为完整datetime格式 first_monday_dates = [pd.Timestamp(f"{y}-{m:02d}-{d}") for (y, m), d in zip(first_mondays.index, first_mondays.index.get_level_values(2))] # 2. 遍历每个周一,找到之后的首个周五 target_fridays = [] for date in first_monday_dates: # 筛选该日期之后的所有周五 candidate_fridays = df[(df.index >= date) & (df['day_of_week'] == 4)] if not candidate_fridays.empty: target_fridays.append(candidate_fridays.index[0]) # 3. 提取目标周五的记录 result = df.loc[target_fridays] print(result)
简化版(适用于无缺失的完整交易日数据)
如果数据是连续无缺失的交易日,可以直接用日期偏移:
import pandas as pd df.index = pd.to_datetime(df.index) # 获取每月第一个周一 first_mondays = df[df['day_of_week'] == 0].groupby([df.index.year, df.index.month]).first() first_monday_dates = [pd.Timestamp(f"{y}-{m:02d}-{d}") for (y, m), d in zip(first_mondays.index, first_mondays.index.get_level_values(2))] # 计算每个周一之后的首个周五 target_fridays = [] for date in first_monday_dates: candidate = date + pd.Timedelta(days=4) if candidate in df.index: target_fridays.append(candidate) else: # 若候选日期不在数据中,找下一个周五 next_friday = candidate + pd.DateOffset(weeks=1) while next_friday not in df.index: next_friday += pd.DateOffset(weeks=1) target_fridays.append(next_friday) result = df.loc[target_fridays] print(result)
补充说明
shift操作仅移动数据,不会修改索引,所以之前用df.shift(-4).index是错误用法,应检查移动后的数据列而非索引。- 处理交易日数据时,必须考虑非交易日缺失,优先用筛选目标日期范围的方式获取结果,避免固定天数偏移的误差。
内容的提问来源于stack exchange,提问作者mike01010
相关产品推荐
相关产品推荐

