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

news2024/11/18 10:33:31

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)

生成报告的结果如下:

图片

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

24、Web攻防——通用漏洞SQL注入MYSQL跨库ACCESS偏移

文章目录 一、SQL注入原理   脚本代码在与数据库进行数据通讯时(从数据库取出相关数据进行页面显示),使用预定义的SQL查询语句进行数据查询。能通过参数传递自定义值来实现SQL语句的控制,执行恶意的查询操作,例如查询…

Kali Linux实现UEFI和传统BIOS(Legacy)引导启动

默认Kali linux安装会根据当前启动的引导模式进行安装 例:以UEFI引导启动安装程序,安装后仅能在UEFI引导模式下进入系统 安装Kali系统 这边基于VirtualBox虚拟机镜像实战操作 首先创建一个Kali虚拟机 这里需要注意,把启动 EFI (只针对某些操作系统)选项勾选上,内存、处理器…

TPS5430正负电源模块

TPS5430正负电源模块 Chapter1 TPS5430正负电源模块一、芯片重要参数二、tps5430参考电路讲解以及PCB布局1.正压降压(15V转12V)2.正压降负压(15V转-12V) Chapter2 使用tps5430制作正负DC-DC降压电源,tps7a47和tps7a33制…

使用sdf文件+urdf文件模拟机器人示例(不用把urdf转sdf)

gazebo版本&#xff1a;harmonic&#xff1b; <launch> <group> <let name"robot_description" value"$(command xacro $(find-pkg-share gazebo_pkg)/urdf/total.xacro)"/> <node pkg"rviz2" exec"rviz2" name…

微信公众号内网穿透本地调试微信授权

微信公众号内网穿透本地调试一直以来都比较麻烦 怕自己忘记&#xff0c; 记录一下 准备 natapp获取一个域名隧道下载nginx配置微信公众号web网页授权域名 1.natapp获取一个域名隧道 在natapp官网&#xff08;https://natapp.cn/&#xff09;进行注册登录后&#xff0c;进入…

零售业物流这个防漏水技术,居然没有翻车!

随着科技的不断发展&#xff0c;水浸监控系统在各个领域得到了广泛应用。水浸监控不仅仅是为了保护建筑结构和设备&#xff0c;更是为了防范因水灾引起的生命安全和财产损失。 因此&#xff0c;为了有效预防和应对水浸事件&#xff0c;水浸监控系统应运而生&#xff0c;成为各行…

基于决策树、随机森林和层次聚类对帕尔默企鹅数据分析

作者&#xff1a;i阿极 作者简介&#xff1a;数据分析领域优质创作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏&#x1f4c1;评论&#x1f4d2;关注哦&#x…

c语言-整型在内存的存储

文章目录 前言一、整型数值在内存中的存储1.1 整型数值的表示形式1.2 二进制的表示形式1.3 整数在内存中存储 二、大端字节序存储和小端字节序存储2.1 大端字节序存储2.2 小端字节序存储2.3 练习 总结 前言 本篇文章叙述c语言中整型数据在内存中的存储方式。 一、整型数值在内…

设计模式:简单工厂模式、工厂方法模式、抽象工厂模式

简单工厂模式、工厂方法模式、抽象工厂模式 1. 为什么需要工厂模式&#xff1f;2. 简单工厂模式2.1. 定义2.2. 代码实现2.3. 优点2.4. 缺点2.5. 适用场景 3. 工厂方法模式3.1. 有了简单工厂模式为什么还需要有工厂方法模式&#xff1f;3.2. 定义3.3. 代码实现3.4. 主要优点3.5.…

在较高时间周期 这些现货黄金投资法值得一用

以日线图和周线图为代表的较高时间周期&#xff0c;一直是投资者很少利用的。之所以这么说&#xff0c;不是说投资者不会在日线图上分析&#xff0c;而是很少利用日线图交易。一来持仓过夜&#xff0c;会有相关的费用产生。二来很多人做现货黄金以短线为主。其实这种较高的时间…

Windows中磁盘未知没有初始化怎么办?

当我们尝试在Windows11/10/8/7上使用外部硬盘驱动器时&#xff0c;在小概率情况下可能会遇到磁盘未知没有初始化情况&#xff0c;此时如果您进入磁盘管理工具中查看&#xff0c;将会发现您的外部硬盘驱动器显示为未知、未初始化、没有磁盘空间&#xff0c;或者在某些情况下它还…

阿里云服务器8080端口安全组开通图文教程

阿里云服务器8080端口开放在安全组中放行&#xff0c;Tomcat默认使用8080端口&#xff0c;8080端口也用于www代理服务&#xff0c;阿腾云atengyun.com以8080端口为例来详细说下阿里云服务器8080端口开启教程教程&#xff1a; 阿里云服务器8080端口开启教程 阿里云服务器8080端…

Mac 安装 Adobe AE/PS 软件报错 “Failed with error code 146“

文章目录 1. 安装 AE 软件报错2. 网上的方法2.1 删除 caps 文件夹2.2 删除 Adobe Sync 文件夹 3. 我的解决方法 1. 安装 AE 软件报错 我在尝试安装 Adobe AE 软件的时候&#xff0c;报错 “Failed with error code 146” 2. 网上的方法 2.1 删除 caps 文件夹 在 finder 的…

众和策略股市行情分析:股票分红是按持股比例来分的吗?

股票分红立足于同股同利的准则&#xff0c;按股东的持股比例来进行股利的派发分红。持股多的股东按比例所得的分红就多&#xff0c;持股少的股东按比例所得的分红就少。 另外&#xff0c;分红详细是指的股票发行公司分配股利的行为。股利包含股息和盈利&#xff0c;股息是指的…

【Web】CTFSHOW元旦水友赛部分wp

目录 ①easy_include ②easy_web ③easy_login web一共5题&#xff0c;我出了3题&#xff0c;巧的是好像师傅们也只出了3题&#xff0c;跨年拿旗还是很快乐的&#xff0c;下面直接贴出自己的wp. ①easy_include pearcmd不解释 这里主要是 &#xff0c;file://协议支持以fi…

Java中的序列化方法探索

.为什么要序列化 对象不序列化&#xff0c;能直接存储吗&#xff1f; 在 Java 中&#xff0c;序列化是将对象的状态信息转换为可以存储或传输的形式&#xff08;例如&#xff0c;转换为字节流&#xff09;的过程。在对象数据需要在网络上传输或需要在磁盘上持久化存储时&#…

Spring Boot学习随笔- 集成MyBatis-Plus(二)条件查询QueryWrapper、聚合函数的使用、Lambda条件查询

学习视频&#xff1a;【编程不良人】Mybatis-Plus整合SpringBoot实战教程,提高的你开发效率,后端人员必备! 查询方法详解 普通查询 // 根据主键id去查询单个结果的。 Test public void selectById() {User user userMapper.selectById(1739970502337392641L);System.out.print…

opencv期末练习题(3)附带解析

创建黑色画板&#xff0c;并支持两种画图功能 import mathimport cv2 import numpy as np """ 1. 创建一个黑色画板 2. 输入q退出 3. 输入m切换画图模式两种模式&#xff0c;画矩形和画圆形。用户按住鼠标左键到一个位置然后释放就可以画出对应的图像 "&qu…

Eureka学习思维导图

一、Eureka Server原理解析 参考&#xff1a;https://www.jianshu.com/p/eb690e6ab11d 二、Eureka Client源码解析 参考&#xff1a;https://www.jianshu.com/p/6e8850387da6

Threejs项目实战之四:实现地图雷达效果

目录 最终效果代码实现创建项目DigitalMapView.vue的核心代码 最终效果 最近事情比较多&#xff0c;今晚难得有空&#xff0c;就抽空完成了一个使用Threejs实现地图雷达扫描效果的程序&#xff0c;下面说下代码实现的原理及核心代码&#xff0c;老规矩&#xff0c;先看下效果图…