Python可视化数据分析-柱状图/折线图

一、前言

使用python编写一个图表生成器,输入各公司的不良品数量,可以在一张图中同时展示数据的柱状图和折线图。

效果如下:

二、基础知识

绘制折线图和柱状图主要使用到了 pyecharts.charts 模块中的 LineBar 类。它们允许用户通过简单的调用方法创建和定制各种样式的折线图和柱状图,从而展示数据分布和趋势。以下是关于这两个类的详细解释:

1)Line类

Line 类用于绘制折线图,展示数据随时间或其他连续变量的变化趋势。以下是一些关键特征和方法 :

创建折线图

from pyecharts.charts import Line

from pyecharts import options as opts 

line_chart = Line()

添加 x 轴和 y 轴数据

line_chart.add_xaxis(["Jan", "Feb", "Mar", "Apr", "May"])
line_chart.add_yaxis("Sales", [150, 230, 224, 300, 290])

设置全局选项

# 设置全局选项,包括标题选项
line_chart.set_global_opts(
    title_opts=opts.TitleOpts(
        title="Sales Trend",  # 设置图表标题为 "Sales Trend"
        subtitle="Monthly Sales",  # 设置图表副标题为 "Monthly Sales"
        pos_left="left",  # 标题靠左显示
        pos_top="top",  # 标题距离顶部位置
        title_textstyle_opts=opts.TextStyleOpts(font_size=20, color="blue")  # 设置标题文本样式
    )
)

渲染和保存

line_chart.render("line_chart.html")

 效果图:

2) Bar类

Bar 类用于绘制柱状图,适用于展示不同类别或组的数据对比。以下是一些关键特征和方法:

创建柱状图: 

from pyecharts.charts import Bar

bar_chart = Bar()

添加 x 轴和 y 轴数据

bar_chart.add_xaxis(["A", "B", "C", "D", "E"])
bar_chart.add_yaxis("Category 1", [25, 40, 60, 55, 75])

设置柱状图特性

bar_chart.set_series_opts(itemstyle_opts=opts.ItemStyleOpts(color="skyblue")) 

设置全局选项:

bar_chart.set_global_opts(title_opts=opts.TitleOpts(title="Bar Chart")) 

渲染和保存

bar_chart.render("bar_chart.html") 

如何使用 LineBar 绘制并渲染折线图和柱状图: 

from pyecharts.charts import Line, Bar
from pyecharts import options as opts

# 创建折线图
line_chart = Line()
line_chart.add_xaxis(["Jan", "Feb", "Mar", "Apr", "May"])
line_chart.add_yaxis("Sales", [150, 230, 224, 300, 290])
line_chart.set_global_opts(title_opts=opts.TitleOpts(title="Sales Trend"))
line_chart.render("line_chart.html")

# 创建柱状图
bar_chart = Bar()
bar_chart.add_xaxis(["A", "B", "C", "D", "E"])
bar_chart.add_yaxis("Category 1", [25, 40, 60, 55, 75])
bar_chart.set_global_opts(title_opts=opts.TitleOpts(title="Bar Chart"))
bar_chart.render("bar_chart.html")

三、编写图表生成器
1)功能需求:

        1.输入各公司每月的不良品数据,可以生成柱状图和折线图。

         2.可以自由添加公司和月份。

        3.折线图和柱状图在同一个表中。

2)代码如下:
import sys
import os
from datetime import datetime
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QPushButton, QLabel, QLineEdit, \
    QMessageBox, QInputDialog
from pyecharts.charts import Line, Bar
from pyecharts import options as opts
import weakref
import webbrowser


class PPMDataInputWidget(QWidget):
    instances = weakref.WeakSet()  # 使用 WeakSet 存储实例

    def __init__(self, company_name, parent=None):
        super().__init__(parent)
        self.company_name = company_name
        self.initUI()
        PPMDataInputWidget.instances.add(self)  # 添加实例到 WeakSet 中

    def initUI(self):
        self.layout = QVBoxLayout()

        # 添加公司名称标签
        company_label = QLabel(f"填写 {self.company_name} 的 不良品 数量:")
        self.layout.addWidget(company_label)

        self.input_fields = {}  # 存储输入框的字典

        # 添加输入框用于填写不定数量的月份 不良品 数量
        self.add_input_field("1月")
        self.add_input_field("2月")
        self.add_input_field("3月")

        # 添加按钮用于增加月份输入框
        add_month_button = QPushButton("添加月份", self)
        add_month_button.clicked.connect(self.add_month_input)
        self.layout.addWidget(add_month_button)

        # 添加删除按钮
        delete_button = QPushButton("删除公司", self)
        delete_button.clicked.connect(self.delete_company)
        self.layout.addWidget(delete_button)

        self.setLayout(self.layout)

    def add_input_field(self, month_name):
        edit = QLineEdit(self)
        edit.setPlaceholderText(f"{month_name}  不良品 数量")
        self.layout.addWidget(edit)
        self.input_fields[month_name] = edit

    def add_month_input(self):
        # 使用对话框获取新的月份名称
        new_month_name, ok = QInputDialog.getText(self, "添加新月份", "输入新月份名称:")
        if ok and new_month_name:
            self.add_input_field(new_month_name)

    def get_ppm_data(self):
        ppm_data = []
        for month_name, edit in self.input_fields.items():
            ppm_value = float(edit.text().strip())
            ppm_data.append(ppm_value)
        return ppm_data

    def delete_company(self):
        reply = QMessageBox.question(self, "确认删除", f"确定要删除 {self.company_name} 吗?",
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.setParent(None)
            self.deleteLater()
            PPMDataInputWidget.instances.discard(self)  # 从 WeakSet 中移除实例


class PPMInputApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("填写 不良品 数量")
        self.setGeometry(100, 100, 600, 400)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        layout = QVBoxLayout()
        central_widget.setLayout(layout)

        # 添加按钮用于添加新公司和月份
        add_company_button = QPushButton("添加公司", self)
        add_company_button.clicked.connect(self.add_company_input_dialog)
        layout.addWidget(add_company_button)

        # 添加按钮用于生成所有公司折线图和柱状图并保存为 HTML
        generate_button = QPushButton("生成所有公司折线图和柱状图并保存为 HTML", self)
        generate_button.clicked.connect(self.generate_all_charts)
        layout.addWidget(generate_button)

        # 添加退出按钮
        exit_button = QPushButton("退出", self)
        exit_button.clicked.connect(self.close)
        layout.addWidget(exit_button)

        self.widgets = []  # 存储 PPMDataInputWidget 的列表

    def add_company_widget(self, company_name):
        widget = PPMDataInputWidget(company_name)
        self.widgets.append(widget)
        layout = self.centralWidget().layout()
        layout.addWidget(widget)

    def add_company_input_dialog(self):
        # 使用对话框获取新公司名称
        new_company_name, ok = QInputDialog.getText(self, "添加新公司", "输入新公司名称:")
        if ok and new_company_name:
            self.add_company_widget(new_company_name)

    def generate_all_charts(self):
        try:
            print("Generating all charts...")
            line_chart = Line()
            bar_chart = Bar()

            # 遍历 WeakSet 中的实例,仅处理存在且有效的部件
            for widget in PPMDataInputWidget.instances:
                if widget.isVisible() and widget in self.widgets:
                    company_name = widget.company_name
                    ppm_data = widget.get_ppm_data()

                    print(f"Processing widget: {company_name}")

                    # 添加折线图数据
                    line_chart.add_xaxis(list(widget.input_fields.keys()))
                    line_chart.add_yaxis(company_name, ppm_data,
                                         markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")]),
                                         label_opts=opts.LabelOpts(formatter="{c}"))

                    # 添加柱状图数据
                    bar_chart.add_xaxis(list(widget.input_fields.keys()))
                    bar_chart.add_yaxis(company_name, ppm_data, gap="0%")  # 设置柱子之间的间距为0%并设置柱子宽度

            # 设置折线图和柱状图的全局选项
            line_chart.set_global_opts(
                # title_opts=opts.TitleOpts(title="各公司 不良品 折线图"),
                # yaxis_opts=opts.AxisOpts(name="数量")
                yaxis_opts=opts.AxisOpts(name="数量", axislabel_opts=opts.LabelOpts(font_weight="bold"))
            )
            bar_chart.set_global_opts(
                # title_opts=opts.TitleOpts(title="各公司 不良品 柱状图"),
                # yaxis_opts=opts.AxisOpts(name="数量")
                yaxis_opts=opts.AxisOpts(name="数量", axislabel_opts=opts.LabelOpts(font_weight="bold"))

            )

            # 叠加折线图和柱状图并保存为 HTML 文件
            overlap_chart = line_chart.overlap(bar_chart)
            # overlap_chart.set_global_opts(
            #     title_opts=opts.TitleOpts(title="折线图和柱状图")
            # )

            # 生成 HTML 文件路径
            timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
            html_file_name = f"all_companies_PPM_{timestamp}.html"
            html_file_path = os.path.join(os.getcwd(), html_file_name)

            # 渲染并打开 HTML 文件
            overlap_chart.render(html_file_path)
            print(f"生成所有公司的 不良品 折线图和柱状图 HTML 文件:{html_file_path}")
            webbrowser.open(f"file://{html_file_path}", new=2)

        except Exception as e:
            print(f"Error occurred during chart generation: {e}")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = PPMInputApp()
    window.show()
    sys.exit(app.exec_())
3)主要功能和结构解析:
  1. PPMDataInputWidget 类

    • 用于创建一个 QWidget 子类,用于输入和展示单个公司的产品不良品数量。
    • 每个实例对应一个公司的数据输入界面。
    • 使用 QVBoxLayout 进行布局管理,包括输入框、添加月份按钮和删除按钮。
    • add_input_field 方法用于添加新的月份输入框。
    • get_ppm_data 方法用于获取输入的不良品数量数据。
    • delete_company 方法用于删除当前公司的输入界面。
  2. PPMInputApp 类

    • 主窗口类,继承自 QMainWindow。
    • 包含添加新公司、生成图表和退出等功能按钮。
    • add_company_widget 方法用于在布局中添加新的 PPMDataInputWidget 实例。
    • generate_all_charts 方法用于生成所有公司的折线图和柱状图,并保存为 HTML 文件。
  3. 关键点解释

    • PPMInputApp 中,通过点击按钮添加新公司,每个公司对应一个 PPMDataInputWidget 实例,用于填写产品不良品数据。
    • 点击生成图表按钮时,遍历所有 PPMDataInputWidget 实例,获取数据并使用 Pyecharts 创建折线图和柱状图。
    • 折线图和柱状图数据使用 add_xaxisadd_yaxis 方法添加,同时设置全局选项,如标题和 Y 轴名称等。
    • 最后将折线图和柱状图叠加在一起,并保存为 HTML 文件,通过 webbrowser.open 打开该文件。
4)打包成exe

 在使用auto-py-to-exe或者Pyinstaller打包程序时,容易报错缺少map_filename.json或者直接缺失pyecharts包。我们在打包时,可以将文件夹一起打包:

pyinstaller --add-data="E:\anaconda3\envs\yolov5\Lib\site-packages\pyecharts;pyecharts" -F -w test.py

结果: 

5)运行

填好数据的效果如下:

 可以点击HTML查看,或者直接下载exe使用。

姐妹篇《Python可视化数据分析-饼状图》 ,欢迎大家一起学习!加电!

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

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

相关文章

拓展网络技能:利用lua-http库下载www.linkedin.com信息的方法

引言 在当今的数字时代,网络技能的重要性日益凸显。本文将介绍如何使用Lua语言和lua-http库来下载和提取LinkedIn网站的信息,这是一种扩展网络技能的有效方法。 背景介绍 在当今科技潮流中,Lua语言以其轻量级和高效的特性,不仅…

【单调栈】力扣85.最大矩形

好久没更新了 ~ 我又回来啦! 两个好消息: 我考上研了,收到拟录取通知啦!开放 留言功能 了,小伙伴对于内容有什么疑问可以在文章底部评论,看到之后会及时回复大家的! 前面更新过的算法&#x…

经典目标检测YOLOV1模型的训练及验证

1、前期准备 准备好目录结构、数据集和关于YOLOv1的基础认知 1.1 创建目录结构 自己创建项目目录结构,结构目录如下: network CNN Backbone 存放位置 weights 权重存放的位置 test_images 测试用的图…

OpenFeign使用demo

OpenFeign使用demo 1. OpenFeign的作用2. OpenFeign使用demo2.1 使用方2.2 提供方 1. OpenFeign的作用 原来我们调用别人的接口,通常都是通过Http请求来(如下图1),而现在有了OpenFeign我们就可以像调用接口的方式来完成调用。 OpenFeign 并不是一个严格…

Leetcode算法训练日记 | day31

专题九 贪心算法 一、分发饼干 1.题目 Leetcode:第 455 题 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的…

Matlab|含sop的配电网重构(含风光|可多时段拓展)

目录 1 主要内容 2 部分程序 3 下载链接 1 主要内容 之前分享了很多配电网重构的程序,每个程序针对场景限定性比较大,程序初学者修改起来难度较大,本次分享一个基础程序,针对含sop的配电网重构模型,含风电和光伏&am…

LeetCode刷题总结 | 图论2—深度优先搜索广度优先搜索较为复杂应用

深搜广搜的标准模版在图论1已经整理过了,也整理了几个标准的套模板的题目,这一小节整理一下较为复杂的DFS&BFS应用类问题。 417 太平洋大西洋水流问题(medium) 有一个 m n 的矩形岛屿,与 太平洋 和 大西洋 相邻…

算法打卡day52|单调栈篇03| 84.柱状图中最大的矩形

算法题 Leetcode 84.柱状图中最大的矩形 题目链接:84.柱状图中最大的矩形 大佬视频讲解:84.柱状图中最大的矩形视频讲解 个人思路 这题和接雨水是相似的题目,原理上基本相同,也是可以用双指针和单调栈解决,只是有些细节不同。…

树莓派3B长时间不操作屏幕息屏无信号处理

树莓派外接显示器,需长时间展示某个网页,经过一段时间,显示器屏幕会黑掉显示无信号。 需修改 /etc/lightdm/lightdm.conf 配置文件中新增如下两行并重启。 xserver-commandX -s 0 dpms sleep-inactive-timeout0

C++相关概念和易错语法(7)(初始化列表、隐式类型转换、友元)

1.初始化列表 初始化列表是集成在构造函数里面的,对象在创建的时候一定会调用构造函数(就算不显式定义,也会自动生成并调用)。初始化列表就是这些对象的成员变量在创建的时候初始化的地方。 下面是使用的例子,可以先…

CCIE-16-PIM

目录 实验条件网络拓朴实验环境实验目的 开始实验实验1:PIM-DM配置PIM域中的路由,开启PIM-DM组播路由功能,验证组播情况 实验2:PIM-SM(静态RP)配置PIM域中的路由,开启PIM-SM组播路由功能&#x…

3-内核开发-第一个字符设备模块开发案例

3-内核开发-第一个字符设备模块开发案例 目录 3-内核开发-第一个字符设备模块开发案例 (1) 字符设备背景介绍 (2) 简单版本字符设备模块 (3) 继续丰富我们的字符驱动模块,增加write,read 功能 (4) 编译执行验证 (5)总结 (6)后记 (7)参考 课程简介&#xff…

[Meachines][Easy]Crafty

Main $ sudo nmap -p- -sS -T4 10.10.11.249 发现25565端口是我的世界服务器端口 CVE-2021-44228: https://nodecraft.com/blog/service-updates/minecraft-java-edition-security-vulnerability在阿帕奇Log4j图书馆,广泛使用的记录框架,在Java应用程序…

一起Talk Android吧(第五百五十七回:如何获取文件读写权限)

文章目录 1. 概念介绍2. 使用方法3. 示例代码4. 内容总结各位看官们大家好,上一回中分享了一个Retrofit使用错误的案例,本章回中将介绍 如何获取文件读写权限。闲话休提,言归正转,让我们一起Talk Android吧! 1. 概念介绍 我们在本章回中说的文本读写权限是指读写手机中的…

0-1背包问题:贪心算法与动态规划的比较

0-1背包问题:贪心算法与动态规划的比较 1. 问题描述2. 贪心算法2.1 贪心策略2.2 伪代码 3. 动态规划3.1 动态规划策略3.2 伪代码 4. C语言实现5. 算法分析6. 结论7. 参考文献 1. 问题描述 0-1背包问题是组合优化中的一个经典问题。假设有一个小偷在抢劫时发现了n个…

CCF-CSP真题《202312-3 树上搜索》思路+c++满分题解

想查看其他题的真题及题解的同学可以前往查看:CCF-CSP真题附题解大全 问题描述 试题编号:202312-3试题名称:树上搜索时间限制:1.0s内存限制:512.0MB问题描述: 题目背景 问题描述 输入格式 输出格式 样…

BioTech - 使用 Amber 工具 松弛(Relaxation) 蛋白质三维结构 (Python)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/137889532 Amber 工具在蛋白质 松弛(Relaxation) 过程中起着重要的作用。在分子动力学模拟中,蛋白质松弛是指模拟过程中蛋白质结构达到一个较为稳定的状态。这个过程通…

SQLite轻量级会话扩展(三十四)

返回:SQLite—系列文章目录 上一篇:SQLite R*Tree 模块(三十三) 下一篇:SQLite—系列文章目录 1. 引言 会话扩展提供了一种方便记录的机制 对 SQLite 数据库中某些表的部分或全部更改,以及 将这些…

视频质量评价 SSIM 算法详细介绍

SSIM SSIM(Structural Similarity Index Measure)是一种用于衡量两幅图像之间相似度的指标,是属于全参考视频质量评价算法范畴;它在图像质量评估领域得到了广泛的应用。SSIM是基于人类视觉系统的特性设计的,它考虑了图像的亮度、对比度和结构信息。SSIM的值范围在-1到1之…

xilinx 7系列FPGA时钟布线资源

7系列FPGA拥有多种时钟路由资源,以支持各种时钟方案和需求,包括高扇出、短传播延迟以及极低的偏斜。为了最佳地利用时钟路由资源,需要了解如何将用户时钟从PCB传递到FPGA,确定哪种时钟路由资源最优,然后通过利用适当的…