我之前使用过时态数据和 matplotlib,所以我知道在 matplotlib 中,日期表示为自纪元以来的 days 数作为浮点数,并且我可以使用
matplotlib.dates
将日期来回转换为浮点数。
尽管如此,我在使用 API 时遇到了一个非常奇怪的问题。 我想创建一个函数来用一些时间注释来装饰绘图,但我不想打印绘图之外的注释。例如,如果绘图回到 2020 年,我不想在 2019 年打印注释。为此,我使用
ax.get_xlim()
并使用 mdates.num2date
将限制转换为日期。
当我用
DateTimeIndex
绘制从 2019 年到 2024 年的 DataFrame 时,我得到了限制 (2599.0, 2860.0)
,转换回日期远不及 2019 年或 2024 年。
代码如下:
pytrends = TrendReq()
pytrends.build_payload(kw_list=['matplotlib', 'seaborn'])
df = pytrends.interest_over_time()
print(df.index)
df.plot()
print(plt.gca().get_xlim())
结果是:
DatetimeIndex(['2019-10-20', '2019-10-27', '2019-11-03', '2019-11-10',
'2019-11-17', '2019-11-24', '2019-12-01', '2019-12-08',
'2019-12-15', '2019-12-22',
...
'2024-08-18', '2024-08-25', '2024-09-01', '2024-09-08',
'2024-09-15', '2024-09-22', '2024-09-29', '2024-10-06',
'2024-10-13', '2024-10-20'],
dtype='datetime64[ns]', name='date', length=262, freq=None)
(np.float64(2599.0), np.float64(2860.0))
我无法用更简单的 DataFrame 重现它。
问题不在于 Matplotlib,而在于 Pandas。事实证明,它没有使用 matplotlib 的 mdates,而是使用名为 PeriodConverter
的自定义转换器如果我删除其中一行,那么它会使用 mdates 转换器。我的解决方案是在装饰绘图的函数中使用
ax.convert_xunits()
:
def add_events(ax=None):
if ax is None:
ax = plt.gca()
xmin, xmax = ax.get_xlim()
# Use enumerate to get same color in line and text
for i,e in enumerate(EVENTS, 1):
if not (xmin <= ax.convert_xunits(e.date) <= xmax):
print(f"Skipping event {e.label}")
continue
ax.axvline(x=e.date, color=f'C{i}', linestyle='--', alpha=.5)
ax.text(
e.date,
.5, # 50% from top
e.label,
color=f'C{i}',
ha='left',
va='top',
transform=ax.get_xaxis_transform(),
rotation=rotation,
)