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

如何基于多条件及关联日期规则过滤pandas DataFrame

原代码错误点
  • 代码里的引号是中文全角符号,yf.download的start和end参数之间缺少逗号,会直接触发语法报错
  • 普通的布尔索引data[cond1 & cond2]只能做同一行内的条件匹配,无法实现「先找符合条件的基准日,再匹配基准日后n天范围内记录」的跨行时间关联逻辑
  • yfinance接口返回的行情数据,日期默认是DataFrame的索引,不是名为Date的普通列,直接访问data['Date']会报KeyError
正确实现方案

先修正基础的数据加载代码,确保时间格式正确:

import yfinance as yf
import pandas as pd

# 替换全角引号为半角,补全参数间逗号
data = yf.download('spy', start='1990-01-01', end='2000-01-01')
# 强制把索引转为datetime类型,避免后续时间计算报错
data.index = pd.to_datetime(data.index)

以下以查找基准日后7天内符合条件记录为例,n可以按需修改:

方法1:逻辑最直观,适合中小数据量

先提取所有基准日,再生成基准日后n天的日期范围,最后做匹配过滤:

n = 7
# 1. 定位所有满足Open>10的基准日期
base_dates = data.index[data['Open'] > 10]
# 2. 生成所有基准日后n天覆盖的日期集合
date_ranges = [pd.date_range(start=d, end=d + pd.Timedelta(days=n)) for d in base_dates]
valid_window_dates = set().union(*date_ranges)
# 3. 最终过滤:日期在窗口范围内,同时满足Open>10、Close<50
result = data[
    data.index.isin(valid_window_dates)
    & (data['Open'] > 10)
    & (data['Close'] < 50)
]

如果不需要包含基准日当天的记录,只看基准日之后的n天,把pd.date_range的start参数改为d + pd.Timedelta(days=1)即可。

方法2:滚动窗口实现,适合大数据量性能优化

用pandas的时间窗口滚动功能,不用预先生成全部日期集合,内存占用更低:

n = 7
# 标记每行自身是否符合Open>10、Close<50的条件
data['self_pass'] = (data['Open'] > 10) & (data['Close'] < 50)
# 滚动7天时间窗口,判断当前日期往前7天内是否存在Open>10的基准日
data['in_valid_window'] = data['Open'].rolling(f'{n}d').apply(lambda x: (x > 10).any()).astype(bool)
# 过滤得到结果,删除临时辅助列
result = data[data['self_pass'] & data['in_valid_window']].drop(columns=['self_pass', 'in_valid_window'])
注意事项
  • 如果你的数据重置过索引,日期变成了名为Date的普通列,把代码里的data.index替换成data['Date']即可
  • 如果只需要匹配交易日,不需要考虑周末、节假日等非交易日,可以把自然日窗口替换为交易日窗口,比如后续5个交易日可以用rolling(5)实现
  • 所有时间偏移计算统一用pd.Timedelta,不要直接给日期类型加整数,会触发类型错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:36:20