Matplotlib中ax.get_xlim与日期轴的异常表现问题
我之前处理过时间数据和Matplotlib相关工作,知道Matplotlib里日期是以自epoch以来的天数浮点数表示的,可通过matplotlib.dates做双向转换。但最近调用API时遇到异常:我想写个函数给绘图添加时间注释,但不想显示绘图范围外的内容,于是用ax.get_xlim()获取范围,再用mdates.num2date转成日期。但当绘制索引为2019至2024的DateTimeIndex类型DataFrame时,得到的范围是(2599.0, 2860.0),转换后的日期和实际范围完全不符,且这个问题用简单DataFrame无法复现。
相关代码
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', ..., '2024-10-20'], dtype='datetime64[ns]', name='date', length=262, freq=None)
(np.float64(2599.0), np.float64(2860.0))
这个问题的核心是pandas的plot方法默认用了自身的日期刻度逻辑,没有调用Matplotlib原生的日期转换,导致get_xlim()返回的不是自epoch以来的天数,而是DataFrame索引的位置序号(从0开始的偏移量)。你可以验证:2860 - 2599 = 261,和DataFrame长度262差1,完全对应索引的位置范围(加上绘图边距后变成2599到2860)。
两种可行解决思路
改用Matplotlib原生绘图
直接用plt.plot()手动传入日期和数据,让Matplotlib用原生日期转换,此时get_xlim()返回的就是正确的epoch天数:import matplotlib.dates as mdates fig, ax = plt.subplots() ax.plot(df.index, df['matplotlib']) ax.plot(df.index, df['seaborn']) xlim_num = ax.get_xlim() print(mdates.num2date(xlim_num)) # 会输出正确的2019-2024范围日期在pandas绘图后手动获取日期范围
若不想修改绘图代码,可直接从DataFrame索引取范围,或结合刻度转换获取实际绘图范围:df.plot() ax = plt.gca() # 直接从索引取原始日期范围 start_date = df.index[0] end_date = df.index[-1] # 或通过刻度转换获取绘图显示的实际范围 xticks_dates = mdates.num2date(ax.get_xticks()) plot_start = xticks_dates[0] plot_end = xticks_dates[-1]
为何简单DataFrame无法复现?
如果测试用的DataFrame是连续高频日期(如每日数据),pandas会自动切换到Matplotlib原生日期处理;但Google Trends返回的是周度离散数据,pandas默认用了基于位置的刻度,才触发这个问题。
内容的提问来源于stack exchange,提问作者David Davó

