在x轴上绘制日期

117

我正在尝试根据日期绘制信息。我有一个日期列表,格式为“01/02/1991”。

我通过以下方式进行转换:

x = parser.parse(date).strftime('%Y%m%d'))

这将给出19910102

然后我尝试使用num2date。

import matplotlib.dates as dates
new_x = dates.num2date(x)

绘图:

plt.plot_date(new_x, other_data, fmt="bo", tz=None, xdate=True)

但是我收到了一个错误。它说“ValueError: year is out of range”。有什么解决办法吗?


2
help(num2date): “x是一个浮点值,它给出自0001-01-01以来的天数加一”,因此x=19910102不对应于1991年1月2日。 - Kyss Tao
这个问题中的解析器是什么? - John Snow
5个回答

187

你可以更简单地使用plot()代替plot_date()来完成这个任务。

首先,将你的字符串转换为Python datetime.date的实例:

import datetime as dt

dates = ['01/02/1991','01/03/1991','01/04/1991']
x = [dt.datetime.strptime(d,'%m/%d/%Y').date() for d in dates]
y = range(len(x)) # many thanks to Kyss Tao for setting me straight here

然后绘制:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator())
plt.plot(x,y)
plt.gcf().autofmt_xdate()

结果:

在这里输入图像描述


13
@bernie 谢谢,真的帮了我很多。但是在我的问题中,有太多天数,所以整个图表变得混乱不堪。如何使用您的方法在 x 轴上显示每第五个日期或每第十个日期?请帮我翻译一下。 - user1506145
2
@erik 我知道有点晚了,但我删除了两个set_major行,这为我解决了问题。失去了一些功能,但仍然有所改善。 - TheBoro
1
不幸的是,它显示给我不是3个日期,而是6个其他日期(尽管在那个区间内)。使用matplotlib-1.5.1。 - Groosha
你的例子(来自2012年)在我这里(2023年)不起作用:我得到了TypeError: float() argument must be a string or a number, not 'datetime.date',针对plt.plot(x, y)。使用的是“Python 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110] on linux”,matplotlib版本为3.7.1。 - PointedEars
你可以使用间隔参数来设置天数,或者使用其他定位器,比如月定位器。例如:plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=7)) - undefined

80

我的声望太低,不能在@ bernie的回复中添加评论,回应@ user1506145。我遇到了同样的问题。

1

解决方法是一个间隔参数,可以解决这个问题。

2

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
import datetime as dt

np.random.seed(1)

N = 100
y = np.random.rand(N)

now = dt.datetime.now()
then = now + dt.timedelta(days=100)
days = mdates.drange(now,then,dt.timedelta(days=1))

plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=5))
plt.plot(days,y)
plt.gcf().autofmt_xdate()
plt.show()

3
请注意,如果您正在获取一系列或指数的第一个日期和最后一个日期,由于这是一个范围,因此最后一个日期将被截断,并且您的代码会出现错误。假设您在索引上有一个“Date”列,则可以执行以下操作:days = mdates.drange(d1.index.min(),d1.index.max() + dt.timedelta(days=1),dt.timedelta(days=1))。本质上,我在范围上限值的日期中添加了1天。 - David Erickson
我应该对Jacek Szałęga的代码进行哪些更改,以便不会在x轴上分配随机日期,而是将从Excel文件中收集/采样的日期放在x轴上? - just_learning
2
最好在这里使用mdates.AutoDateLocator()而不是mdates.DayLocator(interval=5),以自动计算应在x轴上显示多少日期标签。这可能会回答@just_learning上面的问题。 - HongchaoZhang

26

正如@KyssTao所说,help(dates.num2date)指出x必须是一个浮点数,表示从0001-01-01开始的天数再加一。因此,19910102并不是1991年1月2日,因为如果你从0001-01-01开始计算19910101天,你会得到54513年或类似的结果(除以365.25,即每年的天数)。

使用datestr2num代替(请参阅help(dates.datestr2num)):

new_x = dates.datestr2num(date) # where date is '01/02/1991'

7
如果您能添加“import”语句,以帮助像我这样的Python新手,那就太好了。 - kkuilla
如果这还有参考价值,我猜他已经将其作为import matplotlib.dates as dates导入。 - Ira I.I.
@IraI.I. 你是指 from matplotlib import dates 吗? - Shayan

3

将@Jacek Szałęga的答案适用于使用图形fig和对应的坐标轴对象ax

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
import datetime as dt

np.random.seed(1)

N = 100
y = np.random.rand(N)

now = dt.datetime.now()
then = now + dt.timedelta(days=100)
days = mdates.drange(now,then,dt.timedelta(days=1))


fig = plt.figure()
ax = fig.add_subplot(111)
    
ax.plot(days,y)
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=5))
ax.tick_params(axis='x', labelrotation=45)

plt.show()

1
date = raw_date[:20]
# plot lines
plt.plot(date,target[:20] , label = "Real")
plt.xlabel('Date', fontsize=10)
plt.ylabel('Ylabel', fontsize=10)
plt.legend()
plt.title('Date to show')
plt.xticks(date_to_show_as_list,rotation=90)
plt.figure().set_figwidth(30)
plt.show()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接