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日读取的小时数据;完整代码见指定文件夹。
解决方案
问题根源
- 当前X轴使用字符串格式的时间(如"11:00:00"),Matplotlib会将其视为离散分类值,不同日期的相同时间会被当成独立类别,导致刻度重复。
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.
相关产品推荐
相关产品推荐

