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']
核心原因
- 时区/精度不匹配:
result的MultiIndex中的date_是Timestamp对象,若forecast['date']存在时区差异(一个带时区、一个无时区),或日期精度不同(比如原数据有微秒,分组后索引被截断到秒),表面值相同但底层存储的时间戳不一致,导致相等判断不成立。 - 循环覆盖问题:
每次循环都会重新赋值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
相关产品推荐
相关产品推荐

