运行Python代码出现KeyError: ('datetime64[ns]', 'left')错误求解决方案
解决KeyError: ('datetime64[ns]', 'left')问题
嘿,我来帮你搞定这个报错!你遇到的这个KeyError主要是两个原因:一是你用的pandas版本比较旧(看路径是py35的conda环境,pandas版本大概率低于1.0),对datetime64[ns]类型的左闭合IntervalIndex支持不完善;二是原代码里有个潜在问题——当某些时间间隔没有对应数据时,手动分组后的df_res行数和你生成的interval长度不匹配,直接设置索引就会触发错误。
下面给你两个解决方案,优先推荐第一个,简单高效还靠谱:
方案1:用pandas内置的resample直接搞定(最推荐)
你的需求本质就是按固定时间间隔对数据做均值聚合,pandas的resample是专门为这个场景设计的,比自己写循环效率高N倍,还能完美避开手动处理索引的坑:
import pandas as pd import time def transform_in_intervals(df, freq='5T'): df_copy = df.copy() # 确保time列是索引且为datetime类型 df_copy = df_copy.set_index('time', drop=True) # 按5分钟间隔重采样,左闭合,对数值列取均值 # 空的时间段会自动填充NaN,如果你想填充0可以加.fillna(0) resampled_df = df_copy.resample(freq, closed='left').mean(numeric_only=True) return resampled_df start = time.time() trans_df = transform_in_intervals(merged_df) end = time.time() print("time:{:.3f} s".format(end-start))
这个代码不仅简洁,运行速度也会比你原来的循环快很多,完全不需要手动处理区间匹配的逻辑。
方案2:修复原代码的索引问题
如果你一定要用自己写的逻辑,那得解决两个问题:一是保证df_res的行数和interval完全一致,二是兼容旧版本pandas的IntervalIndex问题:
import pandas as pd import time def transform_in_intervals(df,freq=pd.to_offset('5t')): df_copy = df.copy() time_index = df_copy.index # 生成完整的时间间隔序列 interval_count = int((time_index[-1] - time_index[0])/pd.Timedelta(freq)) + 1 interval = pd.interval_range(start=time_index[0], periods=interval_count, freq=freq, closed="left") df_copy.reset_index(drop=False, inplace=True) df_copy['interval'] = pd.NA # 先初始化interval列 i, c = 0, 0 # 给每条数据匹配对应的时间间隔,加边界判断防止越界 while i < len(df_copy) and c < len(interval): if df_copy.loc[i,"time"] in interval[c]: df_copy.loc[i,"interval"] = interval[c] i += 1 else: c += 1 # 先创建以interval为索引的空DataFrame,确保所有时间段都被包含 df_res = pd.DataFrame(index=interval) # 分组聚合后合并到结果中 grouped_data = df_copy.groupby("interval").mean(numeric_only=True).drop("time", axis=1) df_res = df_res.join(grouped_data) return df_res start = time.time() trans_df = transform_in_intervals(merged_df) end = time.time() print("time:{:.3f} s".format(end-start))
这里的关键修改点:
- 初始化
interval列,避免出现未赋值的情况 - 循环里加了
c < len(interval)的判断,防止索引越界 - 先创建完整的Interval索引的DataFrame,再合并分组结果,确保每个时间段都有对应的行
- 用
numeric_only=True避免对非数值列求均值,防止报错
额外提醒
你用的Python3.5和对应的旧版pandas对datetime类型的Interval支持有不少bug,如果环境允许的话,建议升级到pandas1.0以上的版本,能避免很多这类奇怪的索引问题。
内容的提问来源于stack exchange,提问作者MFatn
相关产品推荐
相关产品推荐

