Matplotlib绘制UTC时间柱状图时X轴时间戳错误的解决方法
解决Matplotlib绘制UTC时区时间序列图表偏移问题
问题描述
使用以下代码生成柱状图时,时间序列实际始于2023/01/01 00:00:00+000(UTC),但图表显示数据起始时间偏移至前一天约15:00,推测Matplotlib忽略了数据中的时区信息。需要让图表以UTC时区正确绘图。
原代码
import matplotlib as mplt from matplotlib import dates, pyplot from matplotlib.transforms import ScaledTranslation import numpy as np import pandas as pd ts = pd.date_range('2023/01/01', '2023/01/06', freq='3H', tz='utc') xs = np.arange(len(ts)) df = pd.DataFrame({'date':ts,'value':np.ones(shape=len(ts)), 'intensity':np.random.uniform(0, 10, len(ts))}) colors = [] for i in df.intensity: if 0 <= i < 6: colors.append('#75FF71') elif 6 <= i < 8: colors.append('#FFC53D') else: colors.append('#FF5C5C') # pyplot.box fig, ax = pyplot.subplots(figsize = (24,1), constrained_layout=False) ax.yaxis.set_ticklabels(labels=[]) ax.yaxis.set_visible(False) ax.grid(False) ax.set_frame_on(False) hour_locs = dates.HourLocator(byhour=[6, 12, 18]) hour_locs_fmt = dates.DateFormatter('%H:%M') ax.xaxis.set_minor_locator(hour_locs) ax.xaxis.set_minor_formatter(hour_locs_fmt) day_locs = dates.DayLocator(interval=1) day_locs_fmt = dates.DateFormatter('%B %-d') ax.xaxis.set_major_locator(day_locs) ax.xaxis.set_major_formatter(day_locs_fmt) ax.xaxis.set_tick_params(which='major', pad=-10, length=40) ax.bar(df.date, df.value, color=colors) offset = ScaledTranslation(1.6, 0, fig.dpi_scale_trans) for label in ax.xaxis.get_majorticklabels(): label.set_transform(label.get_transform() + offset)
异常现象
生成的图表中,数据起始时间与实际UTC起始时间不符,偏移至前一天约15:00。
解决方案
问题根源是Matplotlib的日期定位器和格式化器默认会将带时区的datetime转换为本地时区,导致显示偏移。解决核心是给所有日期定位器和格式化器明确指定UTC时区。
修改后的代码
仅需修改日期定位器和格式化器的初始化部分,添加tz='UTC'参数:
import matplotlib as mplt from matplotlib import dates, pyplot from matplotlib.transforms import ScaledTranslation import numpy as np import pandas as pd ts = pd.date_range('2023/01/01', '2023/01/06', freq='3H', tz='utc') xs = np.arange(len(ts)) df = pd.DataFrame({'date':ts,'value':np.ones(shape=len(ts)), 'intensity':np.random.uniform(0, 10, len(ts))}) colors = [] for i in df.intensity: if 0 <= i < 6: colors.append('#75FF71') elif 6 <= i < 8: colors.append('#FFC53D') else: colors.append('#FF5C5C') # pyplot.box fig, ax = pyplot.subplots(figsize = (24,1), constrained_layout=False) ax.yaxis.set_ticklabels(labels=[]) ax.yaxis.set_visible(False) ax.grid(False) ax.set_frame_on(False) # 为定位器和格式化器添加UTC时区参数 hour_locs = dates.HourLocator(byhour=[6, 12, 18], tz='UTC') hour_locs_fmt = dates.DateFormatter('%H:%M', tz='UTC') ax.xaxis.set_minor_locator(hour_locs) ax.xaxis.set_minor_formatter(hour_locs_fmt) day_locs = dates.DayLocator(interval=1, tz='UTC') day_locs_fmt = dates.DateFormatter('%B %-d', tz='UTC') ax.xaxis.set_major_locator(day_locs) ax.xaxis.set_major_formatter(day_locs_fmt) ax.xaxis.set_tick_params(which='major', pad=-10, length=40) ax.bar(df.date, df.value, color=colors) offset = ScaledTranslation(1.6, 0, fig.dpi_scale_trans) for label in ax.xaxis.get_majorticklabels(): label.set_transform(label.get_transform() + offset) pyplot.show()
原理说明
通过给HourLocator、DayLocator以及对应的DateFormatter都指定tz='UTC',强制Matplotlib在解析和格式化日期刻度时使用UTC时区,避免自动转换为本地时区导致的时间偏移,确保图表显示的时间与原始UTC时间序列一致。
内容的提问来源于stack exchange,提问作者AGS
相关产品推荐
相关产品推荐

