如何在Matplotlib直方图的X轴正确显示24小时制时间刻度?
问题描述
我用以下代码读取日志文件并绘制人数随时间变化的直方图:
import cv2 import os import sys import time import matplotlib.pyplot as plt os.chdir('C:/Users/User/anaconda3/envs/yolov7_custom/yolov7-main') number=[] times=[] f=open('log.txt','r') for row in f: row=row.strip().split(' ') if row[0] != '' : number.append(int(row[0])) row5=row[5].split(':') times.append(int(row5[0])*100+int(row5[1])) plt.bar(times,number,color='g',label='File Time') plt.xlabel('Time', fontsize=12) plt.ylabel('Number of people', fontsize=12) plt.show()
日志文件内容如下:
6 03/04/2023 22:13:20 2 03/04/2023 22:14:57 12 03/04/2023 22:18:24 15 03/04/2023 22:20:01 18 03/04/2023 22:21:41 11 03/04/2023 22:23:16 19 03/04/2023 22:24:51 17 03/04/2023 22:26:29 15 03/04/2023 22:28:04 17 03/04/2023 22:29:42 17 03/04/2023 22:31:17 15 03/04/2023 22:32:51 19 03/04/2023 22:34:25 15 03/04/2023 22:36:00 15 03/04/2023 22:37:34 20 03/04/2023 22:39:08 17 03/04/2023 22:40:44 11 03/04/2023 21:47:24 11 03/04/2023 21:48:00
现在生成的直方图X轴显示类似2180的数字,不是标准24小时制时间,还导致数据出现间隙(比如2140之后本该接2200,现在中间空了一大段),该怎么解决?
解决方案
核心问题是你把时间转成了小时*100+分钟的数值,这种数值是非连续的线性值(比如21:59转成2159,下一个小时22:00是2200,中间差了41,和正常分钟间隔不一致),所以X轴会出现不合理的间隙。正确做法是把时间解析成Python的datetime对象或者matplotlib能识别的时间格式,让它自动处理时间轴的显示。
方法一:用datetime解析时间,直接作为X轴
修改代码中读取时间的部分,把每行的日期时间字符串解析成datetime对象,matplotlib会自动识别为时间轴:
import cv2 import os import sys from datetime import datetime import matplotlib.pyplot as plt os.chdir('C:/Users/User/anaconda3/envs/yolov7_custom/yolov7-main') number = [] times = [] with open('log.txt', 'r') as f: for row in f: row = row.strip() if not row: continue # 跳过空行 parts = row.split() # 拼接日期和时间字符串 dt_str = f"{parts[1]} {parts[2]}" # 解析成datetime对象,格式对应日志里的日期时间格式 dt = datetime.strptime(dt_str, "%d/%m/%Y %H:%M:%S") number.append(int(parts[0])) times.append(dt) plt.bar(times, number, color='g', label='File Time') plt.xlabel('Time', fontsize=12) plt.ylabel('Number of people', fontsize=12) # 自动旋转X轴标签,避免重叠 plt.gcf().autofmt_xdate() plt.show()
方法二:转成分钟数,自定义X轴标签
如果只需要小时+分钟的显示,也可以把时间转换成总分钟数(比如21:47就是2160+47=1307分钟,22:00是2260=1320分钟),这样数值是连续的线性值,不会出现间隙。之后再把X轴刻度转换成小时:分钟的格式:
import cv2 import os import sys import matplotlib.pyplot as plt os.chdir('C:/Users/User/anaconda3/envs/yolov7_custom/yolov7-main') number = [] times = [] time_labels = [] # 存显示用的小时:分钟字符串 with open('log.txt', 'r') as f: for row in f: row = row.strip() if not row: continue parts = row.split() hh, mm, ss = parts[2].split(':') total_minutes = int(hh)*60 + int(mm) times.append(total_minutes) number.append(int(parts[0])) time_labels.append(f"{hh}:{mm}") plt.bar(times, number, color='g', label='File Time') plt.xlabel('Time', fontsize=12) plt.ylabel('Number of people', fontsize=12) # 设置X轴刻度为对应的时间标签 plt.xticks(times, time_labels, rotation=45) plt.show()
额外优化点
- 用
with open()代替直接open(),能自动关闭文件,更安全 - 增加空行判断,避免处理无效数据
- 方法一中的
autofmt_xdate()可以自动旋转X轴的时间标签,防止重叠
内容的提问来源于stack exchange,提问作者CKT
相关产品推荐
相关产品推荐

