为什么matplotlib无法正确格式化月度时间序列的x轴日期
问题原因
pandas内置的plot方法会自动根据时间索引的频率选择坐标刻度的计数逻辑:
- 高频的日度及以上粒度数据,默认使用和matplotlib日期模块兼容的日期序数(以公元0年为基准的天数计数),因此用
mdates.DateFormatter解析可以正常显示 - 低频的月度、季度、年度粒度数据,pandas默认会使用自身的周期计数逻辑(以1970年为基准的周期数计数,月度数据就是1970年至今的总月数),而
mdates.DateFormatter会把这个周期数误当成matplotlib的日期天序数解析,最终就会显示为1970年附近的错误日期。
错误的月度数据显示效果如下:
正常的日度数据显示效果如下:
解决方案
调用df.plot时添加x_compat=True参数,强制pandas使用matplotlib兼容的日期序数作为x轴坐标单位,后续的日期格式化逻辑就可以正常生效。
修正后的代码如下:
import numpy as np import pandas as pd import matplotlib.dates as mdates # 提前定义rows变量,原代码缺失该变量定义 rows = 60 # 生成时间序列,切换freq参数即可切换日度/月度 years = pd.date_range(start='1/1/2018', periods=rows, freq='M') # 生成模拟数据 np.random.seed(0) data1 = np.random.randn(len(years)) ts1 = pd.Series(data=data1, index=years) data = {'check': ts1} df = pd.concat(data, axis=1) # 新增x_compat=True参数 ax = df.plot(figsize=(20, 5), x_compat=True) ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y %b"))
如果不想用x_compat参数,也可以改用pandas自带的刻度格式化工具,示例如下:
from matplotlib.ticker import FuncFormatter def date_formatter(x, pos): # 把pandas返回的周期序数转成对应的日期 date = df.index[int(x)] return date.strftime("%Y %b") ax = df.plot(figsize=(20, 5)) ax.xaxis.set_major_formatter(FuncFormatter(date_formatter))
两种方案都可以正确显示月度数据的x轴日期,不会再出现1970年的错误基准。
内容的提问来源于stack exchange,提问作者mnist
相关产品推荐
相关产品推荐

