我有下面的数据框,我正在尝试用这些数据生成表格格式的报告。
import pandas as pd
data = {'MonthString': ['January', 'February', 'March'],
'sachin': [98.08, 99.27, 100.00],
'saurav': ['96.77', '99.85', '98.86']}
df = pd.DataFrame(data)
我想使用 python 的报告实验室库生成以下格式的表格并将其另存为 pdf
| Customer | %Uptime
|----------|--------|--------|---------|
| | Jan | Feb | March |
| |--------|--------|---------|
| Schin | 98.08% | 99.27% | 100.00% |
| Saurav | 96.77% | 99.85 | 98.86% |
下面是我试过的代码
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.pdfgen import canvas
from reportlab.lib import colors
from reportlab.platypus import Table, TableStyle
import pandas as pd
# create the DataFrame
data = {'MonthString': ['January', 'February', 'March'],
'sachin': [98.08, 99.27, 100.00],
'saurav': ['96.77', '99.85', '98.86']}
df = pd.DataFrame(data)
df = df.rename(columns={'MonthString': 'Month'})
df = df.set_index('Month').T.reset_index().rename(columns={'index': 'Customer'})
# create the table
table_data = [list(df.columns)]
for i in range(len(df)):
table_data.append([df.iloc[i][0], *df.iloc[i][1:]])
table = Table(table_data)
table.setStyle(TableStyle([('BACKGROUND', (0,0), (-1,0), colors.gray),
('TEXTCOLOR',(0,0),(-1,0),colors.whitesmoke),
('ALIGN', (0,0), (-1,-1), 'CENTER'),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,0), 14),
('BOTTOMPADDING', (0,0), (-1,0), 12),
('BACKGROUND',(0,1),(-1,-1),colors.beige),
('GRID',(0,0),(-1,-1),1,colors.black)]))
# create the PDF
pdf_file = 'table.pdf'
c = canvas.Canvas(pdf_file, pagesize=letter)
table.wrapOn(c, inch*7, inch*2)
table.drawOn(c, x=50, y=650)
c.save()
但是我无法正确设置表格格式。谁能帮忙?
我稍微改变了你的输入数据框:
df = pd.DataFrame(data)
cols = df.columns.tolist()
for prsn in range(1, df.shape[1]):
df[cols[prsn]] = df[cols[prsn]].apply(lambda x: f'{"{:.2f}".format(float(x))}%')
df = df.T.reset_index()
my_list = [['Customer', '%Uptime']] + df.values.tolist()
my_list[1][0] = my_list[2][0]
并更改了 reportlab TableStyle:
table = Table(my_list)
table.setStyle(TableStyle([('SPAN', (0, 1), (0, 2)),
('SPAN', (1, 0), (-1, 0)),
('BACKGROUND', (0,0), (-1,0), colors.gray),
('TEXTCOLOR',(0,0),(-1,0),colors.whitesmoke),
('ALIGN', (0,0), (-1,-1), 'CENTER'),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,0), 14),
('BOTTOMPADDING', (0,0), (-1,0), 12),
('BACKGROUND',(0,1),(-1,-1),colors.beige),
('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
('GRID',(1, 1), (-1,1),1,colors.black),
('GRID',(0, 0), (-1,0),1,colors.black)] +
[('BOX', (x, 1), (x, -1), 1, colors.black) for x in range(df.shape[1])]))
我认为pdf视图是您现在需要的。
这是获取它的代码:
df = pd.DataFrame(data)
cols = df.columns.tolist()
for prsn in range(1, df.shape[1]):
df[cols[prsn]] = df[cols[prsn]].apply(lambda x: f'{"{:.2f}".format(float(x))}%')
df = df.T.reset_index()
my_list = [['Customer', '%Uptime']] + df.values.tolist()
table = Table(my_list)
table.setStyle(TableStyle([('SPAN', (0, 0), (0, 1)),
('SPAN', (1, 0), (-1, 0)),
('BACKGROUND', (0,0), (-1,0), colors.gray),
('BACKGROUND',(0,1),(-1,-1),colors.beige),
('BACKGROUND', (0,0), (0,1), colors.gray),
('TEXTCOLOR',(0,0),(-1,0),colors.whitesmoke),
('ALIGN', (0,0), (-1,-1), 'CENTER'),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,0), 14),
('BOTTOMPADDING', (0,0), (-1,0), 12),
('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
('GRID',(0, 0), (-1,-1),1,colors.black)]))
此链接可帮助您了解表格样式在 reportlab 中的工作原理: https://docs.reportlab.com/reportlab/userguide/ch7_tables/ 我认为这是很好的解释
几个例子:
这只是基本水平线,在本例中位于第 2 行上方(这意味着第三行,因为 0、1、2)。它是从第 1 列(从一月开始)到最后一列(五月),因为 -1 表示最后一列
('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
# ('GRID',(1, 1), (-1,1),1,colors.black),
# ('GRID',(0, 0), (-1,0),1,colors.black)] +
# [('BOX', (x, 1), (x, -1), 1, colors.black) for x in range(df.shape[1])
]))
它是从第 1 列(第二列因为 0、1)到最后一列因为 -1 的网格。此网格仅在第 1 行(第二行)中,因为开始行 = 1 和停止行 = 1.
#('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
('GRID',(1, 1), (-1,1),1,colors.black),
# ('GRID',(0, 0), (-1,0),1,colors.black)] +
# [('BOX', (x, 1), (x, -1), 1, colors.black) for x in range(df.shape[1])
]))
它是 box ,所以如果我们有例如一个单元格,它将与网格相同。如果我们有整张桌子,我们只会在边框上画线。在我们的例子中,我们有一个包含框的列表,其长度取决于
df.shape[1]
,这意味着从月数+带有客户名称的第一列。由于 -1,我们案例中的每个框都基于一列,从第 1 行(第二行)到最后一行。因此,如果 df.shape[1] == 6
这意味着我们在表中有 6 列,代码创建 6 个从 0 到 5 的框。
#('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
#('GRID',(1, 1), (-1,1),1,colors.black),
#('GRID',(0, 0), (-1,0),1,colors.black),
] + [('BOX', (x, 1), (x, -1), 1, colors.black) for x in range(df.shape[1])]))