如何使用Reportlab在y轴上绘制时间增量数据?

问题描述 投票:0回答:1

刚接触 python 和 reportlab,在线图 y 轴上绘制 timedelta 变量时遇到问题。我正在开发一个程序,该程序读取 Excel 文件并使用 reportlab 生成 pdf 中的图表。 Excel 包含

m:ss.000
格式的时间值,并由 pandas 将其作为字符串读入数据帧。我想以
m:ss:000
格式再次在我的 pdf 中绘制它。据我所知,python 使用 timedelta 以这种方式表示时间,但是当我尝试绘制此图时出现以下错误:
TypeError: '<' not supported between instances of 'Timedelta' and 'int'

我通过将字符串转换为浮点数找到了一个次优的解决方案,例如1:57.123 变成 117.123,我可以用这种方式绘制它,但我仍然更喜欢绘制为 1:57.123。

下面的代码有一个示例数据框,展示了如何获得次优解决方案,以及如何将时间从字符串转换为 timedelta 和浮点数。当我采用相同的方法绘制 timedelta 变量时,出现错误。

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 time_to_float(str):
    temp1 = list(str.split(":"))
    temp2 = list(temp1[1].split("."))
    temp1.pop()

    temp2.insert(0,temp1[0])

    return int(temp2[0])*60 + int(temp2[1]) + int(temp2[2])/1000

doc = SimpleDocTemplate('plot.pdf')
elements = []
styles = getSampleStyleSheet()

df1 = pd.DataFrame({'Lap_Nr': (1,2,3), 'Lap_Time': ('1:57.123', '1:56.988', '1:56.555')})
df2 = pd.DataFrame({'Lap_Nr': (1,2,3), 'Lap_Time': ('1:57.123', '1:56.988', '1:56.555')})

df2.Lap_Time = '00:0' + df2.Lap_Time
df2.Lap_Time = pd.to_timedelta(df2.Lap_Time)

for i in range(0,len(df1)):
    df1.iloc[i,1] = time_to_float(df1.iloc[i,1])

drawing1 = Drawing(400, 200)

chart1 = LinePlot()
chart1.x = 50
chart1.y = 50
chart1.height = 125
chart1.width = 300

chart1.data = [[]]
for i in range(0,3):
    chart1.data[0].append((df1.iloc[i,0], df1.iloc[i,1]))

drawing1.add(chart1)
elements.append(drawing1)

# drawing2 = Drawing(400, 200)

# chart2 = LinePlot()
# chart2.x = 50
# chart2.y = 0
# chart2.height = 125
# chart2.width = 300

# chart2.data = [[]]
# for i in range(0,3):
#     chart2.data[0].append((df2.iloc[i,0], df2.iloc[i,1]))

# drawing2.add(chart2)
# elements.append(drawing2)

doc.build(elements)

有人可以帮我吗?

python reportlab
1个回答
0
投票

更好地使用日期时间并将轴格式设置为 mm:ss (或类似的)。建议使用更通用的绘图库,如 matplotlib。要将绘图从 matplotilb 复制到 reportlab,您可以使用 BytesIO 对象。请参阅下面的示例

from io import BytesIO

import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.dates import DateFormatter

from reportlab.lib.units import cm, inch
from reportlab.lib.utils import ImageReader
from reportlab.pdfgen import canvas


def create_chart():
    df = pd.DataFrame({'Lap_Nr': (1, 2, 3), 'Lap_Time': ('1:57.123', '1:56.988', '1:56.555')})
    df['Lap_Time'] = pd.to_datetime(df['Lap_Time'], format='%M:%S.%f')

    fig, ax = plt.subplots()
    myFmt = DateFormatter("%M:%S.%f")
    ax.yaxis.set_major_formatter(myFmt)

    ax.plot(df['Lap_Nr'], df['Lap_Time'])
    plt.gcf().autofmt_xdate()
    plt.xlabel('Lap Nr')
    plt.ylabel('Lap Time')

    plt.gcf().subplots_adjust(left=0.15)

    imgdata = BytesIO()
    fig.savefig(imgdata, format='png')
    imgdata.seek(0)

    return imgdata


if __name__ == '__main__':
    c = canvas.Canvas('test.pdf')
    Image = ImageReader(create_chart())
    c.drawImage(Image, 2 * cm, 2 * cm, 18 * cm, 12 * cm)
    c.save()
© www.soinside.com 2019 - 2024. All rights reserved.