不同采样率Timedelta索引Pandas DataFrame绘图报错排查
Pandas绘制多DataFrame共享X轴时的TimedeltaIndex报错问题
我通过以下代码将多个带Timedelta索引的Pandas DataFrame绘制到共享X轴上,这些DataFrame的采样率各不相同:
# 数据源 list_of_dfs = [instance.parent_perspective.associated[expression] for expression in instance.parent_perspective.associated] figure, axis = plt.subplots(len(list_of_dfs), 1, sharex=True) for dataframe in list_of_dfs: print(dataframe) for i, dataframe in enumerate(list_of_dfs): ax = dataframe.plot(ax=axis[i])
当按采样率从低到高排序DataFrame列表时,代码能正常运行;但按采样率从高到低排序时,会触发如下错误:
File "C:\Users\[me]\..\[my_script].py", line 110, in [my_script] ax = dataframe.plot(ax=axis[i]) File "C:\Users\[me]\AppData\Roaming\Python\Python310\site-packages\pandas\plotting\_core.py", line 1030, in __call__ return plot_backend.plot(data, kind=kind, **kwargs) File "C:\Users\[me]\AppData\Roaming\Python\Python310\site-packages\pandas\plotting\_matplotlib\__init__.py", line 71, in plot plot_obj.generate() File "C:\Users\[me]\AppData\Roaming\Python\Python310\site-packages\pandas\plotting\_matplotlib\core.py", line 501, in generate self._make_plot(fig) File "C:\Users\[me]\AppData\Roaming\Python\Python310\site-packages\pandas\plotting\_matplotlib\core.py", line 1544, in _make_plot newlines = plotf( File "C:\Users\[me]\AppData\Roaming\Python\Python310\site-packages\pandas\plotting\_matplotlib\core.py", line 1589, in _ts_plot freq, data = maybe_resample(data, ax, kwds) File "C:\Users\[me]\AppData\Roaming\Python\Python310\site-packages\pandas\plotting\_matplotlib\timeseries.py", line 84, in maybe_resample series.index = series.index.asfreq( # type: ignore[attr-defined] AttributeError: 'TimedeltaIndex' object has no attribute 'asfreq'. Did you mean: 'freq'?
数据示例
采样率从低到高排序(正常运行)
value 0 days 00:00:00 0.0 0 days 00:00:00.010000 0.0 0 days 00:00:00.020000 0.0 0 days 00:00:00.030000 0.0 0 days 00:00:00.040000 0.0 ... ... 0 days 00:10:24.950000 0.0 0 days 00:10:24.960000 0.0 0 days 00:10:24.970000 0.0 0 days 00:10:24.980000 0.0 0 days 00:10:24.990000 0.0 [62500 rows x 1 columns] value 0 days 00:00:00 0.0 0 days 00:00:00.010000 0.0 0 days 00:00:00.020000 0.0 0 days 00:00:00.030000 0.0 0 days 00:00:00.040000 0.0 ... ... 0 days 00:10:24.950000 0.1 0 days 00:10:24.960000 0.1 0 days 00:10:24.970000 0.1 0 days 00:10:24.980000 0.1 0 days 00:10:24.990000 0.1 [62500 rows x 1 columns] value -1 days +23:59:59.999100 0.031557 -1 days +23:59:59.999200 0.032379 -1 days +23:59:59.999300 0.031419 -1 days +23:59:59.999400 0.032287 -1 days +23:59:59.999500 0.031857 ... ... 0 days 00:10:24.998600 6.252964 0 days 00:10:24.998700 6.251458 0 days 00:10:24.998800 6.251105 0 days 00:10:24.998900 6.248893 0 days 00:10:24.999000 6.248886 [6250000 rows x 1 columns]
采样率从高到低排序(触发报错)
value -1 days +23:59:59.999100 0.031557 -1 days +23:59:59.999200 0.032379 -1 days +23:59:59.999300 0.031419 -1 days +23:59:59.999400 0.032287 -1 days +23:59:59.999500 0.031857 ... ... 0 days 00:10:24.998600 6.252964 0 days 00:10:24.998700 6.251458 0 days 00:10:24.998800 6.251105 0 days 00:10:24.998900 6.248893 0 days 00:10:24.999000 6.248886 [6250000 rows x 1 columns] value 0 days 00:00:00 0.0 0 days 00:00:00.010000 0.0 0 days 00:00:00.020000 0.0 0 days 00:00:00.030000 0.0 0 days 00:00:00.040000 0.0 ... ... 0 days 00:10:24.950000 0.1 0 days 00:10:24.960000 0.1 0 days 00:10:24.970000 0.1 0 days 00:10:24.980000 0.1 0 days 00:10:24.990000 0.1 [62500 rows x 1 columns] value 0 days 00:00:00 0.0 0 days 00:00:00.010000 0.0 0 days 00:00:00.020000 0.0 0 days 00:00:00.030000 0.0 0 days 00:00:00.040000 0.0 ... ... 0 days 00:10:24.950000 0.0 0 days 00:10:24.960000 0.0 0 days 00:10:24.970000 0.0 0 days 00:10:24.980000 0.0 0 days 00:10:24.990000 0.0
问题分析
报错根源在于Pandas的matplotlib绘图模块在处理共享X轴时,会尝试对后续绘制的DataFrame进行自动重采样以匹配已绘制轴的频率,但TimedeltaIndex并不支持asfreq()方法(该方法仅适用于DatetimeIndex)。当先绘制高采样率DataFrame后,低采样率DataFrame触发了这个无效的重采样逻辑,导致报错。
解决方案
关闭自动重采样
在调用plot()时添加resample=False参数,禁止Pandas自动重采样:for i, dataframe in enumerate(list_of_dfs): ax = dataframe.plot(ax=axis[i], resample=False)转换索引类型
将TimedeltaIndex转换为DatetimeIndex,这样就能支持asfreq()方法。可以选择一个基准时间(比如pd.Timestamp('2020-01-01')),将Timedelta与基准时间相加得到Datetime:base_time = pd.Timestamp('2020-01-01') for df in list_of_dfs: df.index = base_time + df.index保持低采样率优先排序
如果不需要改变排序顺序,继续使用采样率从低到高的排序方式,即可避免触发该错误。
内容的提问来源于stack exchange,提问作者Alrie
相关产品推荐
相关产品推荐

