You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 03:05:11