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

Matplotlib双图X轴格式不匹配问题求助(Pandas读取CSV)

问题

我正在尝试在同一Matplotlib画布中绘制两条曲线,数据来自Pandas读取的CSV文件,需要检测文件中的日期及对应小时数,实现不同日期的小时级数据对比。

当前核心代码片段:

self.excel2 = pandas.read_csv(self.Doc2, sep="\t", encoding="utf-16")
self.excel2.columns = ["Hour", "Date", "Value"]

# 处理第一条曲线数据
for Hour in range(self.DayEndsValue1[0], self.DayEndsValue1[1]): 
    ValueX = self.excel1.loc[Hour, "Hour"]
    self.Plot1X.append(ValueX)

for Value in range(self.DayEndsValue1[0], self.DayEndsValue1[1]):
    ValueY = self.excel1.loc[Value, "Value"]
    self.Plot1Y.append(ValueY)

将读取的值存入列表后绘图,第一条曲线用相同步骤绘制。初始同一日期的双图显示正常,但切换下拉菜单的日期后,X轴出现重复刻度。我希望实现不同时长的日期数据在同一24小时时间轴展示,比如26日11:00至23:55、27日00:00至23:59的曲线能统一显示在00:00-23:59的轴上。

为何X轴无法保持统一的24小时格式?是不是格式设置有误?

我曾尝试用datetime.strptime处理X轴时间值并存入新列表:

for Hour2 in range(self.DayEndsValue2[Index2], self.DayEndsValue2[Index2 + 1]):
    ValueX2 = self.excel2.loc[Hour2, "Hour"]
    self.Plot2X.append(ValueX2)
    hour = dt.datetime.strptime(ValueX2, '%H:%M:%S')
    self.HoursDay2.append(hour.hour)
self.returnedList2 = list(set(self.HoursDay2))

也尝试在绘图后使用mdates的AutoDateLocator和set_major_formatter,但没有效果:

self.FiguraGeneral = plt.figure(figsize=(12, 7), clear=True)
self.FiguraGeneral.clear()

self.FigureBoth = self.FiguraGeneral.add_subplot(111)
self.FigureBoth.plot(self.Plot1X, self.Plot1Y, color="b", label="Presion 1")
self.FigureBoth.scatter(self.Plot2X, self.Plot2Y, color="r", label="Presion 2")

self.FigureBoth.set_title("PRESIONES")
self.FigureBoth.set_xlabel("Hora")
self.FigureBoth.set_ylabel("Presion Ms")

locator = mdates.AutoDateLocator(minticks=12, maxticks=24)
plt.gcf().axes[0].xaxis.set_major_locator(locator)
# plt.gcf().axes[0].xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
plt.xticks(rotation=45)
plt.gcf().autofmt_xdate()

示例:27日读取的小时数据;完整代码见指定文件夹。


解决方案

问题根源

  1. 当前X轴使用字符串格式的时间(如"11:00:00"),Matplotlib会将其视为离散分类值,不同日期的相同时间会被当成独立类别,导致刻度重复。
  2. mdates系列的定位器/格式化器仅对datetime类型数据生效,字符串格式的时间无法触发这些工具的作用。

修复步骤

1. 统一将时间列转换为datetime类型

读取CSV后,直接把Hour列转换成datetime对象(用虚拟日期绑定,仅保留时间信息):

import pandas as pd
import datetime as dt

# 处理第一个文件数据
self.excel1 = pd.read_csv(self.Doc1, sep="\t", encoding="utf-16")
self.excel1.columns = ["Hour", "Date", "Value"]
# 转换Hour列为datetime,用2000-01-01作为虚拟日期
self.excel1["Hour_dt"] = pd.to_datetime(self.excel1["Hour"], format="%H:%M:%S")

# 同理处理第二个文件
self.excel2 = pd.read_csv(self.Doc2, sep="\t", encoding="utf-16")
self.excel2.columns = ["Hour", "Date", "Value"]
self.excel2["Hour_dt"] = pd.to_datetime(self.excel2["Hour"], format="%H:%M:%S")

2. 提取绘图用的datetime时间列表

避免手动循环拼接,直接用Pandas布尔索引切片提取数据:

# 提取第一条曲线的X、Y数据(用Hour_dt作为X轴)
mask1 = (self.excel1.index >= self.DayEndsValue1[0]) & (self.excel1.index < self.DayEndsValue1[1])
self.Plot1X = self.excel1.loc[mask1, "Hour_dt"].tolist()
self.Plot1Y = self.excel1.loc[mask1, "Value"].tolist()

# 提取第二条曲线的X、Y数据
mask2 = (self.excel2.index >= self.DayEndsValue2[Index2]) & (self.excel2.index < self.DayEndsValue2[Index2 + 1])
self.Plot2X = self.excel2.loc[mask2, "Hour_dt"].tolist()
self.Plot2Y = self.excel2.loc[mask2, "Value"].tolist()

3. 统一设置X轴范围和格式

绘图时强制将X轴范围设为00:00到23:59,并用mdates格式化器显示小时:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

self.FiguraGeneral = plt.figure(figsize=(12, 7), clear=True)
self.FigureBoth = self.FiguraGeneral.add_subplot(111)

# 用datetime类型的X轴数据绘图
self.FigureBoth.plot(self.Plot1X, self.Plot1Y, color="b", label="Presion 1")
self.FigureBoth.scatter(self.Plot2X, self.Plot2Y, color="r", label="Presion 2")

# 设置标题和标签
self.FigureBoth.set_title("PRESIONES")
self.FigureBoth.set_xlabel("Hora")
self.FigureBoth.set_ylabel("Presion Ms")

# 设置X轴范围:00:00到23:59
start_time = dt.datetime(2000, 1, 1, 0, 0, 0)
end_time = dt.datetime(2000, 1, 1, 23, 59, 59)
self.FigureBoth.set_xlim(start_time, end_time)

# 设置X轴刻度:每小时一个刻度,显示为HH:MM格式
locator = mdates.HourLocator(interval=1)  # 每小时一个刻度
formatter = mdates.DateFormatter("%H:%M")
self.FigureBoth.xaxis.set_major_locator(locator)
self.FigureBoth.xaxis.set_major_formatter(formatter)

plt.xticks(rotation=45)
plt.gcf().autofmt_xdate()
plt.legend()
plt.tight_layout()

额外优化

  • 避免用for循环手动拼接列表,直接用Pandas布尔索引切片,代码更简洁高效。
  • 虚拟日期(2000-01-01)不影响时间显示,仅用于让datetime类型被Matplotlib正确识别处理。

内容的提问来源于stack exchange,提问作者Fabián Gabriel L.S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:04:52