如何使用Reportlab在Y轴绘制timedelta类型数据?
解决Reportlab折线图Y轴展示timedelta格式时间的问题
问题原因
Reportlab的LinePlot组件不直接支持timedelta类型数据,内部计算轴范围时会将数值与整数做对比,触发TypeError: '<' not supported between instances of 'Timedelta' and 'int'错误。
解决方案
核心思路:用总秒数数值完成图表绘制(复用你已实现的数值转换逻辑),再通过自定义Y轴标签格式化函数,将数值重新转回m:ss.000的时间格式——既保证图表正常渲染,又能展示目标时间样式。
步骤1:优化时间转数值逻辑
用Pandas内置方法简化时间字符串到总秒数的转换,替代手动拆分字符串的函数:
# 直接用Pandas转换,更简洁可靠 df['Lap_Time_Seconds'] = pd.to_timedelta('00:' + df['Lap_Time']).dt.total_seconds()
步骤2:编写Y轴标签格式化函数
将总秒数转回m:ss.000格式:
def format_time_label(seconds): minutes = int(seconds // 60) remaining_sec = seconds % 60 sec_part = int(remaining_sec) ms_part = int((remaining_sec - sec_part) * 1000) return f"{minutes}:{sec_part:02d}.{ms_part:03d}"
步骤3:配置图表Y轴标签
把自定义格式化函数绑定到图表Y轴,替换默认数值标签。
完整修改代码
import pandas as pd from reportlab.lib.styles import getSampleStyleSheet from reportlab.graphics.shapes import Drawing from reportlab.graphics.charts.lineplots import LinePlot from reportlab.platypus import SimpleDocTemplate def format_time_label(seconds): minutes = int(seconds // 60) remaining_sec = seconds % 60 sec_part = int(remaining_sec) ms_part = int((remaining_sec - sec_part) * 1000) return f"{minutes}:{sec_part:02d}.{ms_part:03d}" doc = SimpleDocTemplate('plot_with_time_labels.pdf') elements = [] # 初始化数据并转换为总秒数 df = pd.DataFrame({'Lap_Nr': (1,2,3), 'Lap_Time': ('1:57.123', '1:56.988', '1:56.555')}) df['Lap_Time_Seconds'] = pd.to_timedelta('00:' + df['Lap_Time']).dt.total_seconds() # 创建图表 drawing = Drawing(400, 200) chart = LinePlot() chart.x = 50 chart.y = 50 chart.height = 125 chart.width = 300 # 传入数值型数据 chart.data = [[]] for idx in range(len(df)): chart.data[0].append((df.iloc[idx,0], df.iloc[idx,2])) # 配置Y轴标签使用自定义格式 chart.yValueAxis.labelText = "圈速时间" chart.yValueAxis.valueFormatter = format_time_label drawing.add(chart) elements.append(drawing) doc.build(elements)
关键说明
- 用
pd.to_timedelta+dt.total_seconds()转换时间,比手动拆分字符串更稳定,能处理各类合法时间格式。 - 通过
chart.yValueAxis.valueFormatter属性,让Reportlab渲染Y轴标签时自动调用自定义函数,实现数值到时间格式的转换。 - 这种方式彻底避开了timedelta类型的兼容性问题,同时完美保留了
m:ss.000的展示需求。
内容的提问来源于stack exchange,提问作者Daan Datema
相关产品推荐
相关产品推荐

