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

Pandas日期匹配但过滤返回空DataFrame的问题及解决

问题分析与解决:DataFrame过滤返回空结果的原因及修复方法

问题场景

使用两个pandas DataFrame(result和forecast),希望基于result的索引值过滤forecast,但即使确认date列数据类型均为datetime64[ns]且日期值匹配,过滤得到的comp仍为空。代码如下:

result = forecast.groupby(['date', 'profile', 'combination'])['cur_price'].min().to_frame().fillna(0).astype(int)
for date_, profile, combination in result.index:
    comp = forecast[
        (forecast['date'] == date_) &
        (forecast['profile'] == profile) &
        (forecast['combination'] == combination)
    ]['competitors']

核心原因

  1. 时区/精度不匹配:
    result的MultiIndex中的date_是Timestamp对象,若forecast['date']存在时区差异(一个带时区、一个无时区),或日期精度不同(比如原数据有微秒,分组后索引被截断到秒),表面值相同但底层存储的时间戳不一致,导致相等判断不成立。
  2. 循环覆盖问题:
    每次循环都会重新赋值comp,如果最后一次循环的条件无匹配数据,最终得到的comp就是空DataFrame。

修复方案

方案1:统一日期的时区与精度

如果是时区问题,将两个DataFrame的date字段统一为相同的时区(或都转为无时区):

# 示例:将forecast的date转为无时区(与result索引一致)
forecast['date'] = forecast['date'].dt.tz_localize(None)

# 若存在精度差异,统一截断到相同精度(比如秒)
forecast['date'] = forecast['date'].dt.floor('S')

方案2:用merge替代循环(推荐)

避免循环的低效和类型匹配问题,直接通过合并获取匹配数据:

# 将result的MultiIndex转换为普通列
result_reset = result.reset_index()

# 内连接获取所有匹配的competitors数据
comp = forecast.merge(
    result_reset[['date', 'profile', 'combination']],
    on=['date', 'profile', 'combination'],
    how='inner'
)['competitors']

这种方式无需手动处理类型,效率更高,且能一次性获取所有匹配结果。

方案3:修正循环逻辑(保留循环场景)

如果必须用循环,需统一精度并避免结果覆盖:

import pandas as pd

comp_list = []
for date_, profile, combination in result.index:
    # 统一日期精度
    target_date = date_.floor('S')
    # 过滤匹配行
    matched = forecast[
        (forecast['date'].dt.floor('S') == target_date) &
        (forecast['profile'] == profile) &
        (forecast['combination'] == combination)
    ]['competitors']
    # 收集结果而非覆盖
    comp_list.append(matched)

# 合并所有结果
comp = pd.concat(comp_list)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:33:27