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

news2024/12/23 19:00:47
一、前言

使用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可视化数据分析-饼状图》 ,欢迎大家一起学习!加电!

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

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

相关文章

Java关键字和API

1 this和super关键字 1.this和super的意义 this:当前对象 在构造器和非静态代码块中,表示正在new的对象 在实例方法中,表示调用当前方法的对象 super:引用父类声明的成员 无论是this和super都是和对象有关的。 2.this和sup…

python-自动化篇-终极工具-用GUI自动控制键盘和鼠标-pyautogui-键盘

文章目录 键盘键盘——记忆宫殿入门——通过键盘发送一个字符串——typewrite()常规——键名——typewrite()常规——按下键盘——keyDown()常规——释放键盘——keyUp()升级——热键组合——hotkey() 键盘 pyautogui也有一些函数向计算机发送虚拟按键,让你能够填充…

嵌入式物联网实战开发笔记-乐鑫ESP32芯片功能对比以及功能选型【doc.yotill.com】

乐鑫ESP32入门到精通项目开发参考百例下载: 链接:https://pan.baidu.com/s/1ATvRnAZvxkev-PJfd3EAPg?pwd4e33 提取码:4e33 2.1 初识 ESP32 ESP32-S3 是一款低功耗的 MCU 系统级芯片 (SoC),支持 2.4 GHz Wi-Fi 和低功耗蓝牙 (…

【PythonCode】力扣Leetcode16~20题Python版

【PythonCode】力扣Leetcode16~20题Python版 前言 力扣Leetcode是一个集学习、刷题、竞赛等功能于一体的编程学习平台,很多计算机相关专业的学生、编程自学者、IT从业者在上面学习和刷题。 在Leetcode上刷题,可以选择各种主流的编程语言,如C…

汇编语言(详解)

汇编语言安装指南 第一步:在github上下载汇编语言的安装包 网址:GitHub - HaiPenglai/bilibili_assembly: B站-汇编语言-pdf、代码、环境等资料B站-汇编语言-pdf、代码、环境等资料. Contribute to HaiPenglai/bilibili_assembly development by creat…

一文让你彻底掌握操作符(超详细教程)

✅作者简介:大家好,我是小杨 📃个人主页:「小杨」的csdn博客 🔥系列专栏:小杨带你玩转C语言【初阶】 🐳希望大家多多支持🥰一起进步呀! 大家好呀!我是小杨。小…

学习笔记-数据结构-线性表(2024-04-18)- 单向链表选择排序

试以单向链表为存储结构实现简单选择排序的算法。 实现递增排序,首先选择一个元素作为第一个比较值,遍历其他所有的元素,如果发现其他元素中有比它小的元素,则交换两个元素,这样每一趟都能找到符合要求的最小值 正经…

Turnitin查重时,论文里面的图片会不会被查到?

在撰写论文的时候,论文里面插入几张图片作为观点和数据的阐述在再正常不过了。但是,一旦涉及到论文查重,事情就变得有点复杂了。许多同学早使用Turnitin检测系统(www.checktoo.com)对论文查重时,就常问题到…

记录交叉编译环境配置--海思开发板的 嵌入式nginx和 php的移植

嵌入式 lnmp搭建的记录 一些交叉编译的配置环境思路分享:P:php编译PHP可能遇到的问题configure阶段:Makefile-make阶段:Makefile-make install阶段: N:Nginx 文章比较水,并没有没解决什么实际问…

现货白银保证金交易要先分析趋势

现货白银是保证金交易品种,买卖过程中可能会涉及数十倍的资金杠杆,所以它对投资者的分析水平和交易水平的要求都比较高,所以在进入这个市场之前,投资者需要先学习一些基本的分析方法,当中可以分为基本面和技术面两大流…

2024年外贸独立站建设首选:WordPress引领市场,助力企业出海

随着全球经济的不断融合与发展,越来越多的企业开始关注海外市场,希望通过建设外贸独立站来扩大品牌影响力和销售额。在众多的内容管理系统(CMS)中,WordPress以其强大的功能、丰富的插件资源和用户友好的操作界面&#…

医学临床预测模型发展新趋势-并联式

医学临床预测模型发展新姿势-并联式 现有的预测模型是对单个结局指标进行分类或者回归,得出最终的结论,而辅助医生进行临床决策。众所周知,临床决策过程中,医生通常会考虑多个结局指标来做出最终的决策;临床研究中也通…

多因子模型的因子分组-克隆巴赫α系数

优质博文:IT-BLOG-CN 在建立我们的Alpha模型之前,我们得先知道什么是Alpha?Alpha是一条或者一系列能够预测股票走势的信息资讯组合。而这每一条非随机的信息资讯,我们称之为多因子模型的因子。多因子模型因子的选择需要避免系统性…

苍穹外卖day1--开发环境搭建

整体结构 前端:管理端(Web) 用户端(小程序) 后端:后端服务(Java) 前端工程基于ngnix运行 启动nginx:双击nginx.exe即可启动nginx服务,访问端口号为80 后端…

智慧浪潮下的产业园区:解读智慧化转型如何打造高效、绿色、安全的新产业高地

随着信息技术的飞速发展,智慧化转型已经成为产业园区发展的重要趋势。在智慧浪潮的推动下,产业园区通过集成应用物联网、大数据、云计算、人工智能等先进技术手段,实现园区的智慧化、高效化、绿色化和安全化,从而打造成为新产业高…

网络安全产品---数据库防火墙/审计

数据库防火墙 防火墙的类型繁多,即使下一代防火墙或者说AI防火墙集成功能再多,我觉得waf与数据库防火墙也有其无法被替代的理由,以此记录我对数据库防火墙的理解 what 数据库防火墙是基于数据库协议分析与访问行为控制的数据库安全防护产品…

ZStack教育云计算解决方案入选高质量数字化转型技术解决方案集

近日,中国信通院“铸基计划”《高质量数字化转型技术解决方案(2023年度)》(以下简称“方案集”)发布,云轴科技ZStack智慧教育云计算解决方案入选《高质量数字化转型技术解决方案集》。 为促进数字化转型相…

Kubernetes Pod OOMKilled诊断

Kubernetes Pod OOMKilled诊断 介绍 OOMKilled错误表示容器或pod已被终止,因为它使用的内存多于分配的内存。OOMKilled,通常称为Exit Code 137,是一种源自Linux的错误。OOM(Out of Memory Manager)是Linux系统上的一…

【Flutter】多语言方案二:GetX 版

介绍 多语言方案:GetX版,需要手动自定义字符串引用常量,优点不需要自己管理状态。 目录 介绍运行效果一、安装 GetX二、使用1.语言配置 在lib/core下创建一个language文件夹,文件夹下创建一个local.dart文件2.language文件夹下创…

网络行为分析与异常检测

构建防火墙和使用简单的安全解决方案不足以保护网络免受网络异常或攻击,因为DDoS攻击、未知恶意软件和其他安全威胁一直在上升,改变了网络安全格局。网络管理员必须积极主动地分析网络,获得对网络的完全控制,并全面了解网络流量活…