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

Matplotlib中x轴标签显示与set_xticklabels输入不匹配问题

解决Matplotlib子图时间轴标签显示异常问题

我来帮你搞定这个时间轴标签的问题,先拆解下你遇到的核心问题:


问题分析

  1. 上方子图的“异常”:你看到的异常其实是时间序列x_var1存在间隙(过滤了周末、12点时段和非工作时间),Matplotlib默认按连续时间绘制轴,导致这些间隙被“拉平”,折线看起来像是断开,但数据本身是没问题的。
  2. 下方子图的x轴标签问题:你直接用ax[1].set_xticklabels(x_var1)时,没指定对应的刻度位置(xticks),Matplotlib只会用默认的少量刻度点,对应到x_var1的前几个元素,所以只显示了1月14日的时间,而非完整的日期范围。

解决方案

这里提供两种可行的修正方案,你可以按需选择:

方案1:直接使用时间序列作为x轴(推荐)

既然下方子图的其他元素都正常,我们直接把x_var1作为下方子图的x轴数据,再用Matplotlib的日期格式化工具调整显示,既能保留正确的折线和竖线,又能完美显示时间标签:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
from matplotlib.dates import DateFormatter, HourLocator, DayLocator

np.random.seed(0)
x_var1= pd.date_range(datetime(2014, 1, 14, 9, 0),datetime(2014, 1, 24, 17, 0), freq="30min", tz= 'US/Pacific', closed= 'left' )
x_var1 = x_var1[x_var1.dayofweek < 5]
x_var1= x_var1[x_var1.indexer_between_time('9:00','17:00', include_end= False)]
x_var1= x_var1[x_var1.hour != 12]
y_var1= np.random.normal(loc= 40, scale= 4.4, size= len(x_var1))
int_gap_idx= np.nonzero((x_var1[:-1].hour!= 9) & (x_var1[1:].hour== 9))[0]

fig, ax= plt.subplots(nrows= 2, ncols= 1, figsize=(12, 8))

# 上方子图:修复时间轴显示,添加日期格式化
ax[0].plot(x_var1, y_var1)
ax[0].set_title("Fixed: X-axis and data display are correct")
# 设置日期格式和刻度定位器,避免间隙导致的视觉异常
ax[0].xaxis.set_major_locator(DayLocator())
ax[0].xaxis.set_major_formatter(DateFormatter('%b-%d'))
ax[0].xaxis.set_minor_locator(HourLocator(byhour=[9,11,13,15]))
ax[0].xaxis.set_minor_formatter(DateFormatter('%H:%M'))

# 下方子图:直接使用时间序列作为x轴,保留竖线
ax[1].plot(x_var1, y_var1)
ax[1].set_title("Fixed: X-axis labels are now correct")
# 添加每日开始的竖线(转换为时间点而非索引)
for gap_idx in int_gap_idx:
    ax[1].axvline(x_var1[gap_idx+1], ls= '--', color='gray')

# 设置下方子图的日期格式
ax[1].xaxis.set_major_locator(DayLocator())
ax[1].xaxis.set_major_formatter(DateFormatter('%b-%d'))
ax[1].xaxis.set_minor_locator(HourLocator(byhour=[9,11,13,15]))
ax[1].xaxis.set_minor_formatter(DateFormatter('%H:%M'))

plt.xticks(rotation= 45)
plt.tight_layout()
plt.show()

方案2:手动指定刻度位置和标签(若坚持用索引作为x轴)

如果你想保留x_var2作为x轴,需要手动设置与x_var1关键时间点对应的索引位置,再匹配标签:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime

np.random.seed(0)
x_var1= pd.date_range(datetime(2014, 1, 14, 9, 0),datetime(2014, 1, 24, 17, 0), freq="30min", tz= 'US/Pacific', closed= 'left' )
x_var1 = x_var1[x_var1.dayofweek < 5]
x_var1= x_var1[x_var1.indexer_between_time('9:00','17:00', include_end= False)]
x_var1= x_var1[x_var1.hour != 12]
y_var1= np.random.normal(loc= 40, scale= 4.4, size= len(x_var1))
int_gap_idx= np.nonzero((x_var1[:-1].hour!= 9) & (x_var1[1:].hour== 9))[0]

fig, ax= plt.subplots(nrows= 2, ncols= 1, figsize=(12, 8))

ax[0].plot(x_var1, y_var1)
ax[0].set_title("Except the xaxis label, everything is wrong on this graph")

x_var2= np.arange(len(x_var1))
ax[1].plot(x_var2, y_var1)
ax[1].set_title("Fixed: X-axis labels are now correct")
[ax[1].axvline(gap_index, ls= '--') for gap_index in int_gap_idx]

# 关键:找到每天第一个数据点的索引,作为刻度位置
daily_start_indices = x_var1.groupby(x_var1.date).first().index.get_indexer(x_var1)
daily_start_indices = [i for i in daily_start_indices if i != -1]
# 设置刻度位置和对应的日期标签
ax[1].set_xticks(daily_start_indices)
ax[1].set_xticklabels(x_var1[daily_start_indices].strftime('%b-%d %H:%M'))

plt.xticks(rotation= 45)
plt.tight_layout()
plt.show()

关键知识点

  • 使用set_xticklabels时,必须保证set_xticks指定的位置数量和标签数量一致,否则只会显示部分标签。
  • Matplotlib处理时间序列时,推荐用内置的DateFormatter和Locator工具,能自动处理时间格式和刻度间隔,避免手动踩坑。
  • 上方子图的视觉异常是时间轴连续性导致的,通过设置主次刻度可以让间隙更清晰,折线显示更合理。

内容的提问来源于stack exchange,提问作者mathguy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:23:09