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

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日是周末,数据中无记录),无法对应正确日期。

解决方案

步骤说明

  1. 筛选所有周一,按月份分组取每月第一个周一
  2. 对每个第一个周一,找到之后(含当周)的首个周五
  3. 从原数据中提取这些周五的记录

代码实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 22:50:27