我用 Python 自动生成图文并茂的数据分析报告

reportlab是Python的一个标准库,可以画图、画表格、编辑文字,最后可以输出PDF格式。它的逻辑和编辑一个word文档或者PPT很像。有两种方法:

1)建立一个空白文档,然后在上面写文字、画图等;
2)建立一个空白list,以填充表格的形式插入各种文本框、图片等,最后生成PDF文档。

因为需要产生一份给用户看的报告,里面需要插入图片、表格等,所以采用的是第二种方法。

安装第三方库

reportlab输入Python的第三方库,使用前需要先安装:pip install reportlab

技术交流

独学而无优则孤陋而寡闻,技术要学会交流、分享,不建议闭门造车。

技术交流与答疑、源码获取,均可加交流群获取,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

方式①、微信搜索公众号:Python学习与数据挖掘,后台回复:资料
方式②、添加微信号:dkl88194,备注:资料

我们打造了《数据分析实战案例宝典》,特点:从0到1轻松学习,方法论及原理、代码、案例应有尽有,所有案例都是按照这样的节奏进行表述。
在这里插入图片描述

模块导入

提前导入相关内容,并且注册字体。(注册字体前需要先准备好字体文件)

from reportlab.pdfbase import pdfmetrics   # 注册字体
from reportlab.pdfbase.ttfonts import TTFont # 字体类
from reportlab.platypus import Table, SimpleDocTemplate, Paragraph, Image  # 报告内容相关类
from reportlab.lib.pagesizes import letter  # 页面的标志尺寸(8.5*inch, 11*inch)
from reportlab.lib.styles import getSampleStyleSheet  # 文本样式
from reportlab.lib import colors  # 颜色模块
from reportlab.graphics.charts.barcharts import VerticalBarChart  # 图表类
from reportlab.graphics.charts.legends import Legend  # 图例类
from reportlab.graphics.shapes import Drawing  # 绘图工具
from reportlab.lib.units import cm  # 单位:cm

# 注册字体(提前准备好字体文件, 如果同一个文件需要多种字体可以注册多个)
pdfmetrics.registerFont(TTFont('SimSun', 'SimSun.ttf'))

封装不同内容对应的函数

创建一个Graphs类,通过不同的静态方法提供不同的报告内容,包括:标题、普通段落、图片、表格和图表。函数中的相关数据目前绝大多数都是固定值,可以根据情况自行设置成相关参数。

class Graphs:
    # 绘制标题
    @staticmethod
    def draw_title(title: str):
        # 获取所有样式表
        style = getSampleStyleSheet()
        # 拿到标题样式
        ct = style['Heading1']
        # 单独设置样式相关属性
        ct.fontName = 'SimSun'      # 字体名
        ct.fontSize = 18            # 字体大小
        ct.leading = 50             # 行间距
        ct.textColor = colors.green     # 字体颜色
        ct.alignment = 1    # 居中
        ct.bold = True
        # 创建标题对应的段落,并且返回
        return Paragraph(title, ct)
      
  # 绘制小标题
    @staticmethod
    def draw_little_title(title: str):
        # 获取所有样式表
        style = getSampleStyleSheet()
        # 拿到标题样式
        ct = style['Normal']
        # 单独设置样式相关属性
        ct.fontName = 'SimSun'  # 字体名
        ct.fontSize = 15  # 字体大小
        ct.leading = 30  # 行间距
        ct.textColor = colors.red  # 字体颜色
        # 创建标题对应的段落,并且返回
        return Paragraph(title, ct)

    # 绘制普通段落内容
    @staticmethod
    def draw_text(text: str):
        # 获取所有样式表
        style = getSampleStyleSheet()
        # 获取普通样式
        ct = style['Normal']
        ct.fontName = 'SimSun'
        ct.fontSize = 12
        ct.wordWrap = 'CJK'     # 设置自动换行
        ct.alignment = 0        # 左对齐
        ct.firstLineIndent = 32     # 第一行开头空格
        ct.leading = 25
        return Paragraph(text, ct)

    # 绘制表格
    @staticmethod
    def draw_table(*args):
        # 列宽度
        col_width = 120
        style = [
            ('FONTNAME', (0, 0), (-1, -1), 'SimSun'),  # 字体
            ('FONTSIZE', (0, 0), (-1, 0), 12),  # 第一行的字体大小
            ('FONTSIZE', (0, 1), (-1, -1), 10),  # 第二行到最后一行的字体大小
            ('BACKGROUND', (0, 0), (-1, 0), '#d5dae6'),  # 设置第一行背景颜色
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 第一行水平居中
            ('ALIGN', (0, 1), (-1, -1), 'LEFT'),  # 第二行到最后一行左右左对齐
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 所有表格上下居中对齐
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.darkslategray),  # 设置表格内文字颜色
            ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),  # 设置表格框线为grey色,线宽为0.5
            # ('SPAN', (0, 1), (0, 2)),  # 合并第一列二三行
            # ('SPAN', (0, 3), (0, 4)),  # 合并第一列三四行
            # ('SPAN', (0, 5), (0, 6)),  # 合并第一列五六行
            # ('SPAN', (0, 7), (0, 8)),  # 合并第一列五六行
        ]
        table = Table(args, colWidths=col_width, style=style)
        return table

    # 创建图表
    @staticmethod
    def draw_bar(bar_data: list, ax: list, items: list):
        drawing = Drawing(500, 250)
        bc = VerticalBarChart()
        bc.x = 45       # 整个图表的x坐标
        bc.y = 45      # 整个图表的y坐标
        bc.height = 200     # 图表的高度
        bc.width = 350      # 图表的宽度
        bc.data = bar_data
        bc.strokeColor = colors.black       # 顶部和右边轴线的颜色
        bc.valueAxis.valueMin = 5000           # 设置y坐标的最小值
        bc.valueAxis.valueMax = 26000         # 设置y坐标的最大值
        bc.valueAxis.valueStep = 2000         # 设置y坐标的步长
        bc.categoryAxis.labels.dx = 2
        bc.categoryAxis.labels.dy = -8
        bc.categoryAxis.labels.angle = 20
        bc.categoryAxis.categoryNames = ax

        # 图示
        leg = Legend()
        leg.fontName = 'SimSun'
        leg.alignment = 'right'
        leg.boxAnchor = 'ne'
        leg.x = 475         # 图例的x坐标
        leg.y = 240
        leg.dxTextSpace = 10
        leg.columnMaximum = 3
        leg.colorNamePairs = items
        drawing.add(leg)
        drawing.add(bc)
        return drawing

    # 绘制图片
    @staticmethod
    def draw_img(path):
        img = Image(path)       # 读取指定路径下的图片
        img.drawWidth = 5*cm        # 设置图片的宽度
        img.drawHeight = 8*cm       # 设置图片的高度
        return img

生成报告

if __name__ == '__main__':
    # 创建内容对应的空列表
    content = list()

    # 添加标题
    content.append(Graphs.draw_title('数据分析就业薪资'))

    # 添加图片
    content.append(Graphs.draw_img('抗疫必胜.png'))

    # 添加段落文字
    content.append(Graphs.draw_text('众所周知,大数据分析师岗位是香饽饽,近几年数据分析热席卷了整个互联网行业,与数据分析的相关的岗位招聘、培训数不胜数。很多人前赴后继,想要参与到这波红利当中。那么数据分析师就业前景到底怎么样呢?'))
    # 添加小标题
    content.append(Graphs.draw_title(''))
    content.append(Graphs.draw_little_title('不同级别的平均薪资'))
    # 添加表格
    data = [
        ('职位名称', '平均薪资', '较上年增长率'),
        ('数据分析师', '18.5K', '25%'),
        ('高级数据分析师', '25.5K', '14%'),
        ('资深数据分析师', '29.3K', '10%')
    ]
    content.append(Graphs.draw_table(*data))

    # 生成图表
    content.append(Graphs.draw_title(''))
    content.append(Graphs.draw_little_title('热门城市的就业情况'))
    b_data = [(25400, 12900, 20100, 20300, 20300, 17400), (15800, 9700, 12982, 9283, 13900, 7623)]
    ax_data = ['BeiJing', 'ChengDu', 'ShenZhen', 'ShangHai', 'HangZhou', 'NanJing']
    leg_items = [(colors.red, '平均薪资'), (colors.green, '招聘量')]
    content.append(Graphs.draw_bar(b_data, ax_data, leg_items))

    # 生成pdf文件
    doc = SimpleDocTemplate('report.pdf', pagesize=letter)
    doc.build(content)

生成报告的结果如下:

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/287528.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【设计模式-2】原型模式的原理、代码实现及类图展示

我们一定对类的实例化比较熟悉,前面我们说的单例、还有3种工厂模式都是通过new关键字来创建对象,下面我们来了解一种新的对象创建的方式。 1. 定义 原型模式也是一种创建型的设计模式,实现和原理总体比较简单,一句话总结呢&#…

帮企10合一万能分销商城源码系统:全开源可二开,全端覆盖+完整的代码包以及搭建教程

电商市场的竞争日益激烈,越来越多的企业开始意识到分销商城的重要性。然而,市面上的分销商城系统往往存在着功能单一、扩展性差等问题,无法满足企业的多样化需求。今天来给大家分享一款10合一万能分销商城源码系统。 以下是部分代码示例&…

MYSQL二主二从集群部署

目录 一、环境描述 二、安装mysql 2.1 卸载mysql(如果没安装过,可忽略) 2.1.1 列出安装的mysql 2.1.2 卸载mysql 2.1.3 删除mysql文件目录 2.1.3.1 查看mysql 目录 2.1.3.2 依次删除 2.2 在线安装 2.2.1 下载安装源 2.2.2 安装源rpm 2.2.3 加入rpm密钥 …

西安人民检察院 | OLED翻页查询一体机

产品:55寸OLED柔性屏 项目时间:2023年12月 项目地点:西安 在2023年12月,西安人民检察院引入了OLED翻页查询一体机,为来访者提供了一种全新的信息查询方式。 这款一体机采用55寸OLED柔性屏,具有高清晰度、…

虚幻UE 材质-进阶边界混合之WAT世界对齐纹理

边界混合前篇:虚幻UE 材质-边界混合之PDO像素深度偏移量 上一篇主要讲材质相似或者不同的两个物体之间的边界混合 这一篇主要讲自建材质且相同的两个物体之间的边界混合 文章目录 一、世界对齐纹理二、世界对齐纹理实验1、制作材质 三、进一步优化 一、世界对齐纹理…

25计算机专业考研经验贴之准备篇

Hello各位小伙伴,大家新年好! 马上就要进入寒假假期了,25考研也该提上日程了。今天先跟大家分享一下大家在假期可以先做起来的准备工作。 【选择学校】 择校是个非常重要的内容,因为不同学校的考试内容是不一样的,有些…

免费SSL证书:为你的网站安全护航

SSL证书作为保障网站安全的重要工具,其价值不言而喻。然而,许多人对SSL证书望而却步,因为其高昂的价格让人望而生畏。但现在,我们为您带来了福音——免费SSL证书!让您轻松实现网站安全,无惧网络威胁。 一、…

UTF-8编码文件:有BOM和无BOM的区别

UTF-8编码文件:有BOM和无BOM的区别 在处理UTF-8编码的文本文件时,你可能会遇到“有BOM”和“无BOM”两种类型。了解这两者之间的区别对于确保文件兼容性和正确的数据处理至关重要。 什么是BOM? BOM(Byte Order Mark,…

CRM系统如何实现市场销售管理?CRM系统有哪些营销功能

CRM管理系统中的营销管理模块,它的锋芒常被销售管理所掩盖,但对于企业的业务来说同样重要。营销部门虽然不像销售人员一样直接面对客户,却是挖掘线索、商机的重要角色。CRM在市场营销领域的关键功能包括:营销漏斗、客户细分、营销…

javascript 常见工具函数(五)

41.深度拷贝对象: static deepCopyObj$(obj) {var result Array.isArray(obj) ? [] : {};for (var key in obj) {if (obj.hasOwnProperty(key)) {if (typeof obj[key] object && obj[key] ! null) {result[key] Utils$.deepCopyObj$(obj[key]); //递归…

微信好友添加频繁的原因

01 微信好友添加频繁的原因 1. 添加好友的频率太高:短时间内添加多个好友,系统会认为账号被盗,从而限制用户添加好友; 2. 频繁的发送好友请求:在短时间内连续发送好友请求,也会导致微信限制操作&#xff0…

系列五、搭建Naco(集群版)

一、搭建Naco(集群版) 1.1、前置说明 (1)64位Red Hat7 Linux 系统; (2)64位JDK1.8;备注:如果没有安装JDK,请参考【系列二、Linux中安装JDK】 (3&…

HbuilderX中的git的使用

原文链接https://blog.csdn.net/Aom_yt/article/details/119924356

【C++入门】类和对象(完)

前言 在谈论C时,常常会涉及到一些高级特性和概念,比如初始化列表、static成员、友元、内部类、匿名对象等。这些概念在C编程中起着非常重要的作用,对于想要深入了解C语言的开发者来说,掌握这些知识是至关重要的。本文,…

LeetCode第32题 : 最长有效括号

题目介绍 给你一个只包含 ( 和 ) 的字符串,找出最长有效(格式正确且连续)括号子串的长度。 示例 1: 输入:s "(()" 输出:2 解释:最长有效括号子串是 "()" 示例 2&#xf…

SpringBoot整合mybatis多数据源

废话不多说先上结果 对应数据库 首先导入所需的mybatis、mysql和lombok依赖 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependen…

关于我花费六千多组了台window+Linux主机

一边学习&#xff0c;一边总结&#xff0c;一边分享&#xff01; 写在前面 我在2023年12月组了一台“洋垃圾”的主机&#xff0c;一边当做台式机使用&#xff0c;一边当做服务器使用。这个方案算是相对比较划算的方案。我开始是打算直接单做服务器使用的&#xff0c;以及内存…

【好书推荐】只更新软件,座椅为何能获得加热功能?《一书读懂物联网:基础知识+运行机制+工程实现》

文章目录 什么是OTA&#xff1f;OTA方案的特点时间短、效率高合理使用无线资源&#xff0c;提升终端更新的服务效率高可靠性通用性 OTA系统的参考架构和服务流程结语 2020年&#xff0c;特斯拉发布过一次OTA更新&#xff0c;车主可以通过这次系统更新获得座椅加热功能。当时&am…

微信小程序使用echarts报错 ReferenceError: Image is not defined 解决

报错 ReferenceError: Image is not defined 在用uni-app开发微信小程序时&#xff0c;使用到了echarts&#xff08;V4.6.0&#xff09;配置项中的icon属性&#xff0c;微信开发者工具报错如下&#xff1a; 定位问题 定位问题到了压缩echarts文件中的new Image 使用非压缩…

LiveGBS国标GB/T28181流媒体平台功能-国标级联中作为下级平台对接海康大华宇视华为政务公安内网等GB28181国标平台查看级联状态及会话

LiveGBS国标级联中作为下级平台对接海康大华宇视华为政务公安内网等GB28181国标平台查看级联状态及会话 1、GB/T28181级联是什么2、搭建GB28181国标流媒体平台3、获取上级平台接入信息3.1、如何提供信息给上级3.2、上级国标平台如何添加下级域3.2、接入LiveGBS示例 4、配置国标…