在pandas 0.15中,使用matplotlib绘制datetimeindex时x轴刻度错误,与0.14相比
我创建了一个简单的 pandas 数据框,里面有一些随机值,并且使用了一个日期时间索引,代码如下:
import pandas as pd
from numpy.random import randint
import datetime as dt
import matplotlib.pyplot as plt
# create a random dataframe with datetimeindex
dateRange = pd.date_range('1/1/2011', '3/30/2011', freq='D')
randomInts = randint(1, 50, len(dateRange))
df = pd.DataFrame({'RandomValues' : randomInts}, index=dateRange)
然后我用两种不同的方式来绘制这个数据框:
# plot with pandas own matplotlib wrapper
df.plot()
# plot directly with matplotlib pyplot
plt.plot(df.index, df.RandomValues)
plt.show()
(注意不要同时使用这两个语句,因为它们会在同一个图上绘制。)
我使用的是 Python 3.4 64位 和 matplotlib 1.4。在 pandas 0.14 版本下,这两个语句都能给我预期的图形(它们在 x 轴的格式上稍有不同,这没关系;要注意数据是随机的,所以图形看起来不一样):

但是,当我使用 pandas 0.15 时,pandas 的图看起来还不错,但 matplotlib 的图在 x 轴上出现了一些奇怪的刻度格式:
这种行为有什么好的原因吗?为什么从 pandas 0.14 到 0.15 会发生这样的变化?
3 个回答
import matplotlib.pyplot as plt
plt.figure(figsize=(20, 5))
plt.plot(one_label.index.strftime('%Y-%m'),one_label, label='label')
plt.plot(one_pred.index.strftime('%Y-%m'),one_pred.values, label='pred')
plt.legend()
plt.show()
可以通过使用 .strftime() 来正常显示日期。
在matplotlib 1.5.0版本中,这个功能是直接可以用的:
import pandas as pd
from numpy.random import randint
import datetime as dt
import matplotlib.pyplot as plt
# create a random dataframe with datetimeindex
dateRange = pd.date_range('1/1/2011', '3/30/2011', freq='D')
randomInts = randint(1, 50, len(dateRange))
df = pd.DataFrame({'RandomValues' : randomInts}, index=dateRange)
fig, ax = plt.subplots()
ax.plot('RandomValues', data=df)
注意,这个问题在pandas 0.15.1版本中已经修复了(https://github.com/pandas-dev/pandas/pull/8693),现在使用plt.plot(df.index, df.RandomValues)
就可以正常工作了。
这个行为变化的原因是,从0.15版本开始,pandas的Index
对象不再是numpy的ndarray子类。但真正的原因是matplotlib不支持datetime64
这种数据类型。
作为一种解决方法,如果你想使用matplotlib的plot
函数,可以通过to_pydatetime
把索引转换为Python的日期时间格式:
plt.plot(df.index.to_pydatetime(), df.RandomValues)
更详细的解释:
因为Index
不再是ndarray的子类,matplotlib会把索引转换成一个包含datetime64
类型的numpy数组(而之前,它会保留Index
对象,返回的标量会作为Timestamp
值,这是一种datetime.datetime
的子类,matplotlib可以处理这种类型)。在plot
函数中,它会对输入调用np.atleast_1d()
,这时返回的是一个datetime64数组,而matplotlib会把它当作整数来处理。
我对此开了一个问题(因为这可能会被很多人使用):https://github.com/pydata/pandas/issues/8614