电池数据处理exe 文档说明
一、 需求背景
按照一定的充放电制度,提取不同状态下的电压、电流和放电容量、功率等信息。
1. 输入数据
2. 期望输出结果
例如 如下过程中输出 Volt(V)、 Current(mA) 、Capacity(mAh)、TotalPower(mWh)
- (关键过程1):total cycle =4 Step No. =1
- (关键过程2):total cycle =4 Step No. =3
- (关键过程3):total cycle =5 Step No. =5
- (关键过程4):total cycle =5 Step No. =7
3. 配置文件:json
|
JSON { "input": [{ "Step No.": 1, "Total cycle": 4, "row tail": 1, "row head": 1 }, { "Step No.": 3, "Total cycle": 4, "row tail": 1, "row head": 1 }, { "Step No.": 5, "Total cycle": 5, "row tail": 1, "row head": 1 }, { "Step No.": 7, "Total cycle": 5, "row tail": 1, "row head": 1 } ], "output":[{ "Volt(V)": 10, "Current(mA)": 11, "TotalPower(mWh)": 12, "Capacity(mAh)": 13 }, { "Volt(V)": 10, "Current(mA)": 11, "TotalPower(mWh)": 12, "Capacity(mAh)": 13 }, { "Volt(V)": 10, "Current(mA)": 11, "TotalPower(mWh)": 12, "Capacity(mAh)": 13 }, { "Volt(V)": 10, "Current(mA)": 11, "TotalPower(mWh)": 12, "Capacity(mAh)": 13 } ] }
|
二、业务流程图
三、功能说明
|
序号
|
模块
|
功能
|
功能详细说明
|
备注
|
|
1
|
源文件导入
|
|
|
|
|
2
|
数据清洗
|
|
|
|
|
3
|
数据表结构解析
|
|
|
|
|
4
|
配置文件导入
|
|
|
|
|
5
|
数据分析并输出
|
|
|
|
四、技术应用
1)软件基本配置
Python 安装
Anaconda下载安装与手动配置环境变量
2)python库引用
|
序号
|
引入库
|
引入方式
|
实现功能
|
功能代码参考链接
|
备注
|
|
1
|
xlwings
|
pip install xlwings -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
|
Python中处理Excel的第三方库
|
|
|
|
2
|
pandas
|
pip install pandas -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
|
Python 的核心数据分析支持库
|
|
|
|
3
|
wx
|
pip install wxPython -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
|
wxPython是Python语言的跨平台GUI工具箱
|
|
|
|
4
|
os
|
python自带
|
Python 程序与操作系统进行交互的接口
|
|
|
|
5
|
io
|
python自带
|
Python 处理流的核心工具
|
|
|
|
6
|
tkinter
|
python自带
|
Python的标准Tk GUI工具包
|
https://www.zhangshengrong.com/p/YjNKpkjLXW/
|
|
|
7
|
tkinter.filedialog
|
python自带
|
tkinter中的文件对话框
|
|
|
|
8
|
DataFrame
|
pandas带
|
DataFrame 是由多种类型的列构成的二维标签数据结构
|
|
|
|
9
|
json5
|
pip install json5 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
|
json5是对json的扩展
|
|
|
|
10
|
jsonpath
|
pip install jsonpath -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
|
信息抽取类库,用来解析多层嵌套的json数据
|
|
|
|
11
|
numpy
|
pip install numpy -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
|
Python科学计算的基础包
|
|
|
3) 前端
安装wxFormBuilder
下载链接: wxFormBuilder v3.10.1版本发布了
五、前端页面设计
1) 页面展示
2)页面程序
batteryui2.py
六、后端程序
1)基本框架
|
Python # 首先,咱们从刚刚源文件MyFrame1中将主窗体继承下来.就是修改过name属性的主窗体 class MianWindow(MyFrame1): def init_main_window(self): #最下层的状态文本框赋值 self.m_textCtrl9.SetValue('初始化') #...... if __name__ == '__main__': dfs = [] # 全局变量保存要处理的excel文件数据 selectFileName=''# 全局变量 所选excel文件的绝对工作路径 configFileName=''# 全局变量 所选配置文件的绝对工作路径 app = wx.App() # None表示的是此窗口没有上级父窗体。如果有,就直接在父窗体代码调用的时候填入‘self’就好了。 main_win = MianWindow(None) main_win.init_main_window() main_win.Show() app.MainLoop()
|
Python 中的 if __name__ == '__main__' 该如何理解
2)待处理文件输入:
|
Python #按下按钮,打开文件选择对话框,获得所选文件的绝对路径,读取excel数据 def m_button3OnButtonClick(self, event): global selectFileName #选择本地文件,获得绝对路径,赋值给全局参数selectFileName selectFileName = tk.filedialog.askopenfilename(title='选择文件') #将获得的绝对路径显示在前端文本框中 self.m_textCtrl3.SetValue(selectFileName) global dfs #通过Pandas读取excel文件给变量dt dt=pd.read_excel(selectFileName) #将变量dt的值给全局参数dfs dfs = dt
|
3)数据清理:
|
Python #根据文本框中输入的值,去除excel文件前几行 def m_button31OnButtonClick(self, event): #获得文本框中用户输入的数值 col=int (self.m_textCtrl31.GetValue()) global dfs global selectFileName #将全局参数dfs前col行去掉 dfs.drop(dfs.head(col).index, inplace=True) #清理后的数据重新写入源文件 DataFrame(dfs).to_excel(selectFileName, sheet_name='Sheet1', index=False, header=False) self.m_textCtrl9.SetValue('文件已清理完成,继续下一步')
|
4)文件基本信息展示:
|
Python #读取绝对路径文件,获得文件基本信息 def m_button9OnButtonClick(self, event): global selectFileName buf = io.StringIO() # 创建一个StringIO,便于后续在内存中写入str dfs = pd.read_excel(selectFileName) #按绝对路径读取文件 dfs.info(buf=buf) # 将文件的基本信息写入内存 s = buf.getvalue() # 获得内存中字符串 # 将上述字符串,显示在前端文本框中 self.m_textCtrl5.SetValue(s)
|
5)配置文件输入:
|
Python # 按下按钮,导入配置json def m_button8OnButtonClick(self, event): global configFileName #获得配置json的绝对路径 configFileName = tk.filedialog.askopenfilename(title='选择文件') self.m_textCtrl7.SetValue(configFileName) # 将配置文件的绝对路径显示在前端文本框
|
6)按配置文件进行数据分析、输出结果:
|
Python #对源文件按配置json按规则进行数据提取,存储 def m_button10OnButtonClick(self, event): global configFileName # 配置json'的绝对路径 global selectFileName # 源文件的绝对路径 in_key = [] # 输入文件中的关键列名称 in_value = [] # 输入文件中关键列的数值 out_key= [] # 输出文件中的关键列名称 out_value = [] # 输出文件中的关键列的列值 d_result=[] # 数据分析后保存到结果文件 dfs = pd.read_excel(selectFileName) # 根据绝对路径获得源文件 # 获得配置json obj = json5.load(open(configFileName, 'r', encoding='utf-8')) # 获得json中所有input下的元素列表 key_column = jsonpath.jsonpath(obj, '$.input.*') # 获得json中所有output下的元素列表 key_out = jsonpath.jsonpath(obj, '$.output.*') in_length=len(key_column ) # 获得 key_column列表长度 out_length=len(key_out) # 获得 key_out列表长度 # 遍历input下的元素列表,获取输入文件中的关键列名称,存入in_key; # 遍历input下的元素列表,获取输入文件中的关键列的数值,存入in_value; for list_item in key_column: for k, v in list_item.items(): in_key.append(k) in_value.append(v) # 遍历output下的元素列表,获取输出文件中的关键列名称,存入 out_key; # 遍历output下的元素列表,获取输出文件中的关键列的列值,存入out_value; for list_item1 in key_out: for k1, v1 in list_item1.items(): out_key.append(k1) out_value.append(v1) j = 0 for i in range(in_length): # 获取满足规则的数据在文件表中所在行数(规则是同时满足某一列的列值等于某个值 # &另一列的列值等于某个值的最后一行) k=dfs.loc[(dfs[in_key[j]] == in_value[j]) & (dfs[in_key[j+1]] == in_value[j+1])].tail(in_value[j+2]).index # 获得上述行及之前定义的关键输出列的值形成矩阵给dt dt = dfs.iloc[k, [out_value[j], out_value[j+1], out_value[j+2], out_value[j+3]]] d_result.append(dt) j=j+in_length d_result=pd.DataFrame(np.row_stack(d_result)) # 获得当前工作目录,拼接出输出文件的绝对路径 file=os.path.join(os.getcwd(), 'result.xlsx') DataFrame(d_result).to_excel(file, sheet_name='Sheet1', index=False, header=False) self.m_textCtrl9.SetValue('处理完成,结果文件result.xlsx')
|
7)完整源程序
|
Python import xlwings as xw import pandas as pd import wx import os import io import tkinter as tk import tkinter.filedialog from pandas import DataFrame import json5 import jsonpath import numpy as np
from UI.batteryui2 import MyFrame1
# 首先,咱们从刚刚源文件中将主窗体继承下来.就是修改过name属性的主窗体咯。 class MianWindow(MyFrame1):
# 咱们给个初始化函数,将文本框初始填有‘主窗口测试’几个字 # 不能直接覆盖原有__ini__方法,这样会导致窗体启动失败。咱们新建一个,然后再调用
def init_main_window(self): self.m_textCtrl9.SetValue('初始化')
def m_button3OnButtonClick(self, event): global selectFileName selectFileName = tk.filedialog.askopenfilename(title='选择文件') self.m_textCtrl3.SetValue(selectFileName) global dfs dt=pd.read_excel(selectFileName) dfs = dt
def m_button31OnButtonClick(self, event): col=int (self.m_textCtrl31.GetValue()) global dfs global selectFileName dfs.drop(dfs.head(col).index, inplace=True) DataFrame(dfs).to_excel(selectFileName, sheet_name='Sheet1', index=False, header=False) self.m_textCtrl9.SetValue('文件已清理完成,继续下一步')
def m_button9OnButtonClick(self, event): global selectFileName
buf = io.StringIO() # 创建一个StringIO,便于后续在内存中写入str dt = pd.read_excel(selectFileName) dt.info(buf=buf) # 写入 s = buf.getvalue() # self.m_textCtrl5.SetValue(s)
def m_button8OnButtonClick(self, event): global configFileName configFileName = tk.filedialog.askopenfilename(title='选择文件') self.m_textCtrl7.SetValue(configFileName)
def m_button10OnButtonClick(self, event): global configFileName global selectFileName in_key = [] in_value = [] out_key= [] out_value = [] d_result=[] dfs = pd.read_excel(selectFileName) obj = json5.load(open(configFileName, 'r', encoding='utf-8')) key_column = jsonpath.jsonpath(obj, '$.input.*') key_out = jsonpath.jsonpath(obj, '$.output.*') in_length=len(key_column ) out_length=len(key_out) for list_item in key_column: for k, v in list_item.items(): in_key.append(k) in_value.append(v) for list_item1 in key_out: for k1, v1 in list_item1.items(): out_key.append(k1) out_value.append(v1) j = 0 for i in range(in_length): k=dfs.loc[(dfs[in_key[j]] == in_value[j]) & (dfs[in_key[j+1]] == in_value[j+1])].tail(in_value[j+2]).index dt = dfs.iloc[k, [out_value[j], out_value[j+1], out_value[j+2], out_value[j+3]]] d_result.append(dt) j=j+4 d_result=pd.DataFrame(np.row_stack(d_result)) file=os.path.join(os.getcwd(), 'result.xlsx') DataFrame(d_result).to_excel(file, sheet_name='Sheet1', index=False, header=False) self.m_textCtrl9.SetValue('处理完成,结果文件result.xlsx')
if __name__ == '__main__': dfs = [] # showList也是全局变量 selectFileName='' configFileName='' app = wx.App() # None表示的是此窗口没有上级父窗体。如果有,就直接在父窗体代码调用的时候填入‘self’就好了。 main_win = MianWindow(None) main_win.init_main_window() main_win.Show() app.MainLoop()
|