Python pandas 0.21.0与matplotlib的时间戳兼容性问题
我刚刚将pandas从0.17.1更新到0.21.0,以利用一些新功能,并遇到了与matplotlib的兼容性问题(我还更新到了最新的2.1.0)。特别是,Timestamp对象似乎发生了显著的变化 我碰巧有另一台机器仍在运行pandas(0.17.1)/matplotlib(1.5.1)的旧版本,我用它来比较差异: 两个版本都将我的数据帧索引显示为Python pandas 0.21.0与matplotlib的时间戳兼容性问题,python,pandas,matplotlib,plot,Python,Pandas,Matplotlib,Plot,我刚刚将pandas从0.17.1更新到0.21.0,以利用一些新功能,并遇到了与matplotlib的兼容性问题(我还更新到了最新的2.1.0)。特别是,Timestamp对象似乎发生了显著的变化 我碰巧有另一台机器仍在运行pandas(0.17.1)/matplotlib(1.5.1)的旧版本,我用它来比较差异: 两个版本都将我的数据帧索引显示为dtype='datetime64[ns] DatetimeIndex(['2017-03-13', '2017-03-14', ... '2017
dtype='datetime64[ns]
DatetimeIndex(['2017-03-13', '2017-03-14', ... '2017-11-17'], type='datetime64[ns]', name='dates', length=170, freq=None)
但是当调用type(df.index[0])
时,0.17.1给出pandas.tslib.Timestamp
,0.21.0给出pandas.\u libs.tslib.Timestamp
使用df.index
作为x轴打印时:
plt.plot(df.index, df['data'])
默认情况下,matplotlibs将x轴标签格式化为pandas 0.17.1的日期,但无法识别pandas 0.21.0的日期,只给出原始编号1.5e18
(纪元时间单位为纳秒)
我还有一个自定义光标,它通过在x值上使用matplotlib.dates.DateFormatter
报告图表上单击的位置,该值在0.21.0时失败,具有:
OverflowError: signed integer is greater than maximum
我可以在调试中看到,对于0.17.1,报告的x值约为736500(即从0年开始的天数),但对于0.21.0,报告的x值约为1.5e18(即纳秒历元时间)
我很惊讶matplotlib和pandas之间兼容性的中断,因为它们显然被大多数人一起使用。对于较新版本,我调用上面的plot函数的方式是否遗漏了什么
Update如上所述,我更喜欢使用给定的Axis对象直接调用plot
,但为了检查一下,我尝试调用数据帧本身的plot方法df.plot()
。完成后,所有后续绘图都会正确识别同一python会话中的时间戳。就好像设置了一个环境变量,因为我可以重新加载另一个数据帧或使用子批次创建另一个轴,而1.5e18
在哪里不显示。正如最新的熊猫博士所说,这闻起来真像一只虫子:
但是很明显,它对python会话做了一些事情,以便后续的绘图正确地处理时间戳索引
事实上,只需在上述链接上运行示例:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
根据是否调用ts.plot()
,以下绘图是否将x轴正确格式化为日期:
plt.plot(ts.index,ts)
plt.show()
调用成员plot后,随后调用新系列或数据帧上的plt。plot
将自动正确格式化,无需再次调用成员plot方法。最近发布的pandas 0.21中有一个版本,在导入时不再注册其转换器。一旦您使用这些转换器一次(在pandas中),它们也将被注册并自动由matplotlib使用
解决方法是手动注册它们
import pandas.plotting._converter as pandacnv
pandacnv.register()
无论如何,这个问题在pandas和matplotlib方面都是众所周知的,所以下一个版本将有一些修复。熊猫们正在考虑一个即将发布的版本。所以这个问题可能只是暂时的。还有一个选项是在不应出现这种情况的情况下恢复到0.20.x
更新:matplotlib(2.2.2)/pandas(0.23.1)的当前版本不再存在此问题,可能许多版本都是从2017年12月左右发布的,当时已修复此问题
更新2:从0.24或更高版本开始,建议使用以下方法注册转换器:
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
或者,如果已将pandas
作为pd
导入
pd.plotting.register_matplotlib_converters()
在打开pandas github上的一个应用程序后,我了解到这确实是pandas和matplotlib之间关于单元转换器自动注册的一个已知的例子。事实上,它被列在我以前没有看到的新功能上,以及注册转换器的正确方法:
from pandas.tseries import converter
converter.register()
这也是第一次在序列或数据帧上调用成员plot方法时完成的,这解释了我在上面观察到的情况
这样做的目的似乎是为了让matplotlib实现对pandas datetime的一些基本支持,但实际上,某种类型的弃用警告对于这种中断可能很有用。然而,在matplotlib真正实现这种支持(或某种延迟注册机制)之前,实际上我总是将这两行放在导入中。因此,我不确定pandas为什么要在matplotlib端准备就绪之前禁用导入时的自动注册。看来matplotlib的未来版本已经解决了这个问题
尝试运行“pip安装--升级matplotlib”
我遇到了相同的问题“AttributeError:'numpy.datetime64'对象没有属性'toordinal'。升级matplotlib包时已修复。没错,我在pandas github上打开的问题上也得到了类似的响应。我在熊猫网站上发布了一个稍微正式一点的方法,我已经尝试过了。你在这里也尝试过这个方法吗?你能报告它是否有效吗(理论上应该有效,但我无法尝试,如果无效,我最好删除答案)。我确实尝试过,但也有效——我最终使用了熊猫网站上的两行文字,因为它们更可能是未来的证明。这一问题已于2019年5月13日返回。我正在使用matplotlib(3.0.3)和pandas(0.24.2)。但是,显式注册转换器确实可以解决这个问题。希望这可以长期解决。@Ben是的,我用目前推荐的注册转换器的方法更新了答案。
from pandas.tseries import converter
converter.register()