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 webbrowserclass PPMDataInputWidget(QWidget):instances = weakref.WeakSet()  # 使用 WeakSet 存储实例def __init__(self, company_name, parent=None):super().__init__(parent)self.company_name = company_nameself.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] = editdef 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_datadef 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)# 添加按钮用于生成所有公司折线图和柱状图并保存为 HTMLgenerate_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_nameppm_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使用。

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

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

相关文章

完整、免费的把pdf转word文档

在线工具网 https://www.orcc.online/pdf 支持pdf转word,免费、完整、快捷 登录网站 https://orcc.online/pdf 选择需要转换的pdf文件: 等待转换完成 点击蓝色文件即可下载 无限制,完整转换。

动态IP与静态IP的区别,你选对了吗?

在互联网世界中,IP地址是每台设备在网络上的唯一标识。这些地址可以是动态的,也可以是静态的。对于非专业人士来说,理解这两者之间的区别可能会有些困难。本文旨在深入探讨动态IP和静态IP的主要差异,帮助读者根据自己的需求做出明…

vue 如何调用子组件内的方法

在Vue中&#xff0c;子组件的方法可以通过父组件的该子组件的引用来调用。 在父组件中&#xff0c;给子组件添加一个ref属性&#xff0c;用来获取子组件的引用。例如&#xff1a; <template><div><child-component ref"child"></child-compon…

Golang | Leetcode Golang题解之第37题解数独

题目&#xff1a; 题解&#xff1a; func solveSudoku(board [][]byte) {var line, column [9][9]boolvar block [3][3][9]boolvar spaces [][2]intfor i, row : range board {for j, b : range row {if b . {spaces append(spaces, [2]int{i, j})} else {digit : b - 1line…

docker网路和主机通讯问题

#注 1&#xff0c;安装docker和启动容器服务的时候如果防火墙处于开启状态&#xff0c;那么重启docker里面的容器的时候必须开启防火墙&#xff0c;否则会出现iptable错误&#xff1b; 2&#xff0c;linux开启防火墙会导致主机和docker网络之间单向通讯&#xff0c;主机可以访…

一周IT资讯

又降了&#xff1f;运维4月平均月薪1W6&#xff1f; 薪资作为大部分人的主要收入来源&#xff0c;是每个人最关注的话题之一。 最近&#xff0c;小编搜索了近半年的运维薪资趋势&#xff0c;看看你的钱包缩水了没&#xff1f; *数据来自看准网 据了解&#xff0c;运维2024年…

单链表详解(无哨兵位),实现增删改查

1.顺序表对比单链表的缺点 中间或头部插入时&#xff0c;需要移动数据再插入&#xff0c;如果数据庞大会导致效率降低每次增容就需要申请空间&#xff0c;而且需要拷贝数据&#xff0c;释放旧空间增容造成浪费&#xff0c;因为一般都是以2倍增容 2.链表的基础知识 链表也是线…

LeetCode---128双周赛

题目列表 3110. 字符串的分数 3111. 覆盖所有点的最少矩形数目 3112. 访问消失节点的最少时间 3113. 边界元素是最大值的子数组数目 一、字符串的分数 按照题目要求&#xff0c;直接模拟遍历即可&#xff0c;代码如下 class Solution { public:int scoreOfString(string …

C语言入门算法——爬楼梯(了解动态规划)

题目描述&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1. 1 阶 1 阶…

java锁面试题

这里写目录标题 1.悲观锁和乐观锁2.悲观锁和乐观锁的场景3.自旋锁和自适应自旋锁4.无锁、偏向锁、轻量级锁、重量级锁5.公平锁和非公平锁6.可重入锁7.排他锁和共享锁8.锁优化技术 1.悲观锁和乐观锁 悲观锁&#xff1a;在修改数据时&#xff0c;一定有别的线程来使用&#xff0…

代码随想录算法训练营第三十二天| LeetCode122.买卖股票的最佳时机II、LeetCode55.跳跃游戏、LeetCode45.跳跃游戏II

LeetCode 122 买卖股票的最佳时机II 题目链接&#xff1a;122. 买卖股票的最佳时机 II - 力扣&#xff08;LeetCode&#xff09; 【解题思路】 利润当天成交价-昨天成交价 当遇到利润为正数的情况&#xff0c;将其收集。 【解题步骤】 1.定义一个result&#xff0c;将每天…

如何使用ArcGIS Pro进行路径分析

路径分析是一种空间分析技术&#xff0c;用于确定两个或多个地点之间最佳路径或最短路径&#xff0c;这里为大家介绍一下在ArcGIS Pro中如何进行路径分析&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的道路数据&#xff0c;除了道路数据&a…

阿里TTl使用管理日志

在管理日志的时候我们需要查看生成日志都是那些人干了那些事&#xff0c;那么怎么在日志上查看这些事情呢&#xff0c;首先呢可以直接使用Slf4j,然后再配置文件里配置一下 #日志文件最大上限 logging.file.max-size100MB #日志文件存储位置 logging.file.path./logs #日志文件…

中颖51芯片学习7. ADC模数转换

中颖51芯片学习7. ADC模数转换 一、ADC工作原理简介1. 概念2. ADC实现方式3. 基准电压 二、中颖芯片ADC功能介绍1. 中颖芯片ADC特性2. ADC触发源&#xff08;1&#xff09;**软件触发**&#xff08;2&#xff09;**TIMER4定时器触发**&#xff08;3&#xff09;**外部中断2触发…

面试: 悲观锁和乐观锁

一、悲观锁的代表是synchronized和Lock 锁 其核心思想是【线程只有占有了锁&#xff0c;才能去操作共享变量&#xff0c;每次只有一个线程占锁成功&#xff0c;获取锁失败的线程&#xff0c;都得停下来等待】线程从运行到阻塞、再从阻塞到唤醒&#xff0c;涉及线程上下文切换&a…

【设计模式】装饰模式

目录 什么是装饰模式 代码实现 什么是装饰模式 Java装饰模式是一种结构型设计模式&#xff0c;它允许你动态地将新功能附加到对象上&#xff0c;通过将对象包装在一个装饰器对象中。这种模式能够在不修改现有对象结构的情况下&#xff0c;灵活地添加功能。 在Java中&#xf…

vue ---列表渲染

1.基本列表 v-for指令: 用于展示列表数据语法&#xff1a;v-for“(item, index) in xxx” :key“yyy”.可遍历&#xff1a;数组、对象、字符串&#xff08;用的很少&#xff09;、指定次数&#xff08;用的很少&#xff09; <!DOCTYPE html> <html><head>&l…

CTFHub(web sql注入)(三)

MYSQL 手工注入 1.判断字段数 输入1 输入2 输入3 得知字段有两个 2.判断注入类型 1 and 1 1 1 and 12 回显错误&#xff0c;说明存在sql注入 3.查看数据库内容 知道字段数量为2后&#xff0c;可以查看数据库位置 1 union select 1,2 使用union select 1,2查看未发现数…

【Java基础】21.重写(Override)与重载(Overload)

文章目录 一、重写(Override)1.方法重写2.方法的重写规则3.Super 关键字的使用 二、重载(Overload)1.方法重载2.重载规则3.实例 三、重写与重载之间的区别 一、重写(Override) 1.方法重写 重写&#xff08;Override&#xff09;是指子类定义了一个与其父类中具有相同名称、参…

阿里云OSS 存储对象的注册与使用

目录 一、什么是阿里云OSS 二、 点击免费试用 2.1 选择第一个&#xff0c;点击免费试用 ​编辑 2.2 登录管理控制台 2.3 进入Bucket 2.4、在阿里云网站上的个人中心配置Accesskey,查询accessKeyId和accessKeySecret。 2.5、进入AccssKey管理页面应该会出现下图提示&…