在pandas 0.15中,使用matplotlib绘制datetimeindex时x轴刻度错误,与0.14相比

17 投票
3 回答
54047 浏览
提问于 2025-04-29 05:38

我创建了一个简单的 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.14: pandas plot

pandas 0.14: matplotlib plot

但是,当我使用 pandas 0.15 时,pandas 的图看起来还不错,但 matplotlib 的图在 x 轴上出现了一些奇怪的刻度格式:

pandas 0.15: pandas plot

pandas 0.15: matplotlib plot

这种行为有什么好的原因吗?为什么从 pandas 0.14 到 0.15 会发生这样的变化?

暂无标签

3 个回答

0
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() 来正常显示日期。

3

在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)

演示图片

26

注意,这个问题在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

撰写回答