如何在Matplotlib中绘制日期与时间散点图并正确设置刻度
问题原因
你两次报错的根源如下:
- 第一次报错是因为matplotlib的散点图接口默认需要数值型输入,不能直接识别
datetime.time类型的y值 - 第二次报错是因为
matplotlib.dates.date2num方法仅支持传入包含完整日期+时间的datetime.datetime对象,单独的datetime.time没有日期上下文,无法完成转换
另外注意不要用dict作为变量名,这是Python内置的关键字,会覆盖原有功能。
完整可运行实现代码
import datetime from matplotlib import pyplot as plt import matplotlib.dates as mdates from matplotlib.ticker import FuncFormatter # 原始数据,修改变量名避免关键字冲突 time_records = { datetime.date(2021, 11, 1): [datetime.time(7, 43, 23)], datetime.date(2021, 11, 8): [datetime.time(6, 4, 45), datetime.time(6, 3, 36), datetime.time(5, 56, 26)], datetime.date(2021, 11, 12): [datetime.time(8, 5, 11), datetime.time(5, 44, 45), datetime.time(5, 24, 14), datetime.time(4, 56, 5)] } fig, ax = plt.subplots() # 处理数据并绘制散点 for date, time_list in time_records.items(): # x轴转成matplotlib识别的日期数值 x = [mdates.date2num(date)] * len(time_list) # y轴将时间转成当日0点以来的总秒数,也可以除以3600转成小时数 y = [t.hour * 3600 + t.minute * 60 + t.second for t in time_list] ax.scatter(x, y) # ------------------- 刻度自定义设置 ------------------- # x轴设置:按年-月-日格式显示 ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) # x轴刻度自动旋转避免文字重叠 fig.autofmt_xdate() # y轴设置:将总秒数转回时分秒格式显示 def format_y_tick(sec, _): hour = int(sec // 3600) minute = int((sec % 3600) // 60) second = int(sec % 60) return f"{hour:02d}:{minute:02d}:{second:02d}" ax.yaxis.set_major_formatter(FuncFormatter(format_y_tick)) # 可选:根据数据范围设置y轴区间为0点到9点 ax.set_ylim(0, 9*3600) plt.tight_layout() plt.show()
问题解答
1. Matplotlib处理datetime对象的方法
- 对于完整的
datetime.datetime类型、datetime.date类型,可以直接用matplotlib.dates.date2num()方法转成matplotlib内部使用的浮点型日期数值,大部分绘图接口也支持直接传入这两类datetime对象作为x轴数据,无需手动转换。 - 对于单独的
datetime.time类型,需要先做数值转换:要么转成当天0点以来的总秒数/总小时数,要么给它拼接一个固定的虚拟日期转成完整的datetime对象再处理。
2. datetime相关的刻度设置方法
- 日期类刻度:用
matplotlib.dates模块下的DateFormatter指定显示格式,常见格式符:%Y四位年、%m两位月、%d两位日、%H两位小时、%M两位分钟、%S两位秒;还可以配合DayLocator、HourLocator等类自定义刻度的生成间隔。 - 自定义数值转时间的刻度:用
matplotlib.ticker.FuncFormatter自定义转换函数,把你转成的数值(比如总秒数)再转成可读的时间字符串显示即可。
内容的提问来源于stack exchange,提问作者user136555
相关产品推荐
相关产品推荐

