它是由AutoDateLocator
. 似乎此错误尚未报告给问题跟踪器。
它看起来很奇怪,只是因为绘制了太多的标签和刻度。
当使用带有日期的数据进行绘图时,默认情况下,matplotlibmatplotlib.dates.AutoDateLocator
用作主要定位器。即,AutoDateLocator
用于确定刻度间隔和刻度位置。
假设,数据序列由 给出[datetime(2013, 1, 1), datetime(2013, 5, 18)]
。
时间增量为 4 个月零 17 天。月增量为 4,日增量为 4*31+17=141。
根据matplotlib 文档:
类 matplotlib.dates.AutoDateLocator(tz=None, minticks=5, maxticks=None, interval_multiples=False)
minticks 是所需的最小刻度数,用于选择刻度类型(每年、每月等)。
maxticks 是所需的最大滴答数,它控制滴答之间的任何间隔(每隔一个、每 3 个等)。对于真正细粒度的控制,这可以是一个字典,将单个规则频率常数(每年、每月等)映射到它们自己的最大刻度数。这可用于保持刻度数适合于在 class:AutoDateFormatter 中选择的格式。此字典中未指定的任何频率都被赋予默认值。
AutoDateLocator 有一个间隔字典,它映射滴答的频率(来自 dateutil.rrule 的常数)和该滴答允许的倍数。默认如下所示:
self.intervald = {
YEARLY : [1, 2, 4, 5, 10],
MONTHLY : [1, 2, 3, 4, 6],
DAILY : [1, 2, 3, 7, 14],
HOURLY : [1, 2, 3, 4, 6, 12],
MINUTELY: [1, 5, 10, 15, 30],
SECONDLY: [1, 5, 10, 15, 30]
}
间隔用于指定适合滴答频率的倍数。例如,对于每日刻度,每 7 天是合理的,但对于分钟/秒,15 或 30 是有意义的。您可以通过执行以下操作自定义此字典:
由于月 delta 为 4,小于 5,而日 delta 为 141,不小于 5。tick 的类型将是每天。
在解析了tick的类型后,AutoDateLocator
会使用interval字典和maxticks字典来确定tick的间隔。
当maxticks
is时None
,AutoDateLocator
使用其默认的 maxticks 字典。文档向我们展示了默认的区间字典,并没有告诉我们默认的 maxticks 字典是什么样的。
我们可以在dates.py中找到它。
self.maxticks = {YEARLY : 16, MONTHLY : 12, DAILY : 11, HOURLY : 16,
MINUTELY : 11, SECONDLY : 11}
确定刻度间隔的算法是
# Find the first available interval that doesn't give too many ticks
for interval in self.intervald[freq]:
if num <= interval * (self.maxticks[freq] - 1):
break
else:
# We went through the whole loop without breaking, default to 1
interval = 1
滴答的类型是DAILY
现在。日差141 也是freq
如此。上面的代码将等价于DAILY
num
for interval in [1, 2, 3, 7, 14]:
if 141 <= interval * (11 - 1):
break
else:
interval = 1
141 太大了。所有的每日间隔都会给出太多的滴答声。else
子句将被执行,刻度间隔将设置为 1。
这意味着将绘制 140 多个标签和刻度。我们可以期待一个丑陋的 x 轴。
如果数据序列由 给出[datetime(2013, 1, 1), datetime(2013, 5, 17)]
,则仅短一天。日期增量为 140。然后AutoDateLocator
将选择 14 作为刻度间隔,并且仅绘制 10 个标签。因此,您的第一张图看起来不错。
实际上我不明白为什么如果maxticks
约束不能满足,matplotlib 选择将间隔设置为 1。如果间隔为 1,它只会导致更多的滴答声。我更喜欢使用最长的间隔。
结论:
给定范围大于或等于 4 个月 18 天且小于 5 个月的任何日期序列,AutoDateLocator
将选择 1 作为刻度间隔。当使用默认的主要定位器(即AutoDateLocator
.
解决方案:
最简单的解决方案是将每日 maxticks 增加到 12。例如:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.dates import DAILY
from datetime import datetime
ax = plt.subplot(111)
plt.plot_date([datetime(2013, 1, 1), datetime(2013, 5, 31)],
[datetime(2013, 1, 1), datetime(2013, 5, 10)])
loc = ax.xaxis.get_major_locator()
loc.maxticks[DAILY] = 12
plt.show()