基于Webio交互的Pyecharts数据分析脚本小记
1 概述
由于工作原因,需要把期货品种的交易数据以板块分类,然后统计出来。每次在Excel上做虽然不难,但也繁琐,遂想把这一工作写成脚本,一劳永逸。
实现效果如下:
对数据分类和统计倒是不难,但使用了第三方库 #Webio来交互,#Pyecharts来显示,#Pyinstaller来打包,尤其是打包过程颇费心力。趁着热乎劲儿记到这里,即为自己以后查看,也为有需要的人提供借鉴。
直接贴上代码:
#!/usr/bin/env python
# coding: utf-8import warnings
import pandas as pd
from pywebio.input import file_upload
from pyecharts.charts import Bar #导入需要使用的图表
from pyecharts import options as opts #导入配置项
from pyecharts.globals import ThemeType
from pywebio.output import put_column, put_htmlwarnings.filterwarnings("ignore")# 读取文件函数
def read_in():file = file_upload('请选择需要加载的数据')df1 = pd.read_excel(file['content'])df2 = (df1['合约'].str.extract(r'(?P<品种>.*?)(?P<月份>\d+(?:\.\d+)?)').applymap(str.strip))data = pd.concat([df1, df2], axis=1).drop('合约', axis=1)return data# 计算函数
def process(data):# 读入数据data = datadata['板块'] = '---'# 根据类别打标签for i in range(len(data)):if data['品种'][i] in 贵金属: data['板块'][i] = '贵金属'if data['品种'][i] in 有色: data['板块'][i] = '有色'if data['品种'][i] in 煤焦钢矿: data['板块'][i] = '煤焦钢矿'if data['品种'][i] in 非金属建材: data['板块'][i] = '非金属建材'if data['品种'][i] in 能源: data['板块'][i] = '能源'if data['品种'][i] in 化工: data['板块'][i] = '化工'if data['品种'][i] in 谷物: data['板块'][i] = '谷物'if data['品种'][i] in 油脂油料: data['板块'][i] = '油脂油料'if data['品种'][i] in 软商品: data['板块'][i] = '软商品'if data['品种'][i] in 农副产品: data['板块'][i] = '农副产品'if data['品种'][i] in 金融期货: data['板块'][i] = '金融期货'# 构造输出结果result = pd.DataFrame(columns=['多头市值', '多头市值占比', '空头市值', '空头市值占比', '轧差市值'], index=sector)# 根据源数据计算多头空头市值for i in range(len(sector)):result.loc[sector[i]].多头市值 = data[(data['板块'] == sector[i]) & (data['卖持仓'] == 0)].sum().持仓市值 # 多头result.loc[sector[i]].空头市值 = data[(data['板块'] == sector[i]) & (data['买持仓'] == 0)].sum().持仓市值 # 空头# 计算总市值TMV = result.多头市值.sum() - result.空头市值.sum() # TMV:Total Market Value# 计算市值占比和轧差市值result.多头市值占比 = pd.DataFrame.abs(result.多头市值 / TMV)result.空头市值占比 = pd.DataFrame.abs(result.空头市值 / TMV)result.轧差市值 = result.多头市值 - result.空头市值long = []short = []for i in range(len(result.多头市值.tolist())):long.append(round(float(result.多头市值占比.tolist()[i]), 2))short.append(round(float(result.空头市值占比.tolist()[i]), 2))result.多头市值占比 = pd.DataFrame.abs(result.多头市值 / TMV).map(lambda x: format(x, '.0%'))result.空头市值占比 = pd.DataFrame.abs(result.空头市值 / TMV).map(lambda x: format(x, '.0%'))return result, long, short# 画柱状图函数
def create_bar(bar_dict):# 建立百分比的柱状图bar_item = bar_dict['item']bar_head = bar_dict['head']bar_data = bar_dict['data']bar = (Bar(init_opts=opts.InitOpts(height="400px", width="600px", theme=ThemeType.WHITE)).add_xaxis(bar_item))for i in range(len(bar_head)):bar.add_yaxis(bar_head[i], bar_data[i], label_opts=opts.LabelOpts(formatter="{c} %"))bar.set_global_opts(yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value} %"), interval=10))bar.set_global_opts(title_opts=opts.TitleOpts(title='板块市值占比'),xaxis_opts=opts.AxisOpts(name_rotate=60, name="板块", axislabel_opts={"rotate": 45}),yaxis_opts=opts.AxisOpts(name="市值占比(%)"))return bar# 获取数据函数
def get_data_dict():# 这里获取要显示的数据 , 可以改成连接数据库data_a = [round(n * 100, 2) for n in long]data_b = [round(n * 100, 2) for n in short]pdt_list = sector.tolist()data_dict = {'data': [data_a, data_b], 'head': ['多头市值', '空头市值'], 'item': pdt_list}return data_dict# 分类方法
贵金属 = ['au', 'ag']
有色 = ['al', 'pb', 'ni', 'zn', 'sn', 'cu', 'bc']
煤焦钢矿 = ['SM', 'SF', 'i', 'jm', 'hc', 'ss', 'wr', 'j', 'rb']
非金属建材 = ['FG', 'bb', 'v', 'fb']
能源 = ['pg', 'lu', 'sc', 'fu', 'ZC']
化工 = ['MA', 'eg', 'TA', 'UR', 'eb', 'PF', 'l', 'bu', 'sp', 'nr', 'pp', 'ru', 'SA']
谷物 = ['WH', 'c', 'rr', 'RI', 'JR', 'LR', 'PM']
油脂油料 = ['y', 'a', 'RM', 'p', 'RS', 'OI', 'm', 'b', 'PK']
软商品 = ['CF', 'CY', 'SR']
农副产品 = ['CJ', 'jd', 'cs', 'AP', 'lh']
金融期货 = ['T', 'TS', 'TF', 'IF', 'IH', 'IC', 'IM']# 板块分类
sector = pd.Series(['贵金属', '有色', '煤焦钢矿', '非金属建材', '能源', '化工', '谷物', '油脂油料', '软商品', '农副产品', '金融期货'])if __name__ == "__main__":data = read_in() # 读取数据result, long, short = process(data) #data_dict = get_data_dict()bar = create_bar(data_dict)put_column([put_html(bar.render_notebook()),put_html(result.to_html(border=0)),]).show()
2 说一下值得记录的点:
2.1 根据字符和数字分列
原数据是这样的格式:
其中【合约】由前半部分的字符和后半部分的数字组成,为了处理方便需要将二者分开,然后放到不同的列里。此动作的核心代码如下:
df2 = (df1['合约'].str.extract(r'(?P<品种>.*?)(?P<月份>\d+(?:\.\d+)?)').applymap(str.strip))
1.2 Pyecharts生成带百分比的柱状图
本来Pyecharts画图不难,但生成百分比的标签有些繁琐,核心代码如下:
# 画柱状图函数
def create_bar(bar_dict):# 建立百分比的柱状图bar_item = bar_dict['item']bar_head = bar_dict['head']bar_data = bar_dict['data']bar = (Bar(init_opts=opts.InitOpts(height="400px", width="600px", theme=ThemeType.WHITE)).add_xaxis(bar_item))for i in range(len(bar_head)):bar.add_yaxis(bar_head[i], bar_data[i], label_opts=opts.LabelOpts(formatter="{c} %"))bar.set_global_opts(yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value} %"), interval=10))bar.set_global_opts(title_opts=opts.TitleOpts(title='板块市值占比'),xaxis_opts=opts.AxisOpts(name_rotate=60, name="板块", axislabel_opts={"rotate": 45}),yaxis_opts=opts.AxisOpts(name="市值占比(%)"))return bar
麻烦的关键点在于数字格式只能是小数,百分比格式只能是字符串。
这是因为Pyecharts对输入数据的要求比较苛刻,要求规整的【list】形式,且【list】内的元素必须是【int】。
笔者用Pandas构造的DataFrame,使用to_list命令后虽然可以得到【list】格式,但其中的元素却是【numpy.int64】,所以一直识别不了,卡住了很久。
所以使用下述函数对数据进行规整:
# 获取数据函数
def get_data_dict():# 这里获取要显示的数据 , 可以改成连接数据库data_a = [round(n * 100, 2) for n in long]data_b = [round(n * 100, 2) for n in short]pdt_list = sector.tolist()data_dict = {'data': [data_a, data_b], 'head': ['多头市值', '空头市值'], 'item': pdt_list}return data_dict
原理就是遍历旧list后放到新列表中,以待输入画图函数中。
2.3 使用Pywebio库输入和输出
这是个蛮有趣的库,可以利用浏览器进行数据交互,既可以做本地脚本,也可以部署到网络。本项目只是用了基础的脚本模式,做到输入和输出。
2.3.1 输入
输入还是比较简单的,只需要使用file_upload函数唤起浏览器即可。
唤起的浏览器输入页面如下,直接选择对应的文件就好,笔者这里的文件是Excel.xls格式。
核心代码如下:
file = file_upload('请选择需要加载的数据')
df1 = pd.read_excel(file['content'])
2.3.2 输出
输出过程也只用到了基础的部分,本来想做成横向排版,但排版总不合适,最终选择的是竖向排列。输出的结果是一个图和一个表,其中表格是DataFrame格式转换成Html格式后输出的。
效果如下:
可以看到左右留白还是很多的,如果是横向排版会更合适,就先留着日后深化吧。
核心代码如下:
put_column([put_html(bar.render_notebook()),put_html(result.to_html(border=0))
可以看到不管是输入还是输出,Pywebio的代码实现都相当简洁,这里要给开发者点个大大的赞!
2.4 打包
打包真的很麻烦,尤其是对Pywebio和Pyecharts的打包试了很多次都不行。这方面笔者还不太懂,这里只是将自己的排错过程放到这里仅供参考。
2.4.1 首先在工作目录下使用如下命令生成spec文件:
pyi-makespec -c -F main.py
其中“main.py”应该改成实际要打包的脚本名字。
2.4.2 然后在相应目录中找到spec文件并打开,进行以下编辑:
from pywebio import STATIC_PATHa = Analysis(...datas=[(STATIC_PATH, 'pywebio/html'), (STATIC_PATH+'/../platform/tpl', 'pywebio/platform/tpl')],...
)
2.4.3 接着使用以下命令打包:
pyinstaller main.spec
打包完成后会在dist文件夹里找到.exe可执行文件,然后并没有完事大吉,运行此文件会发现报错,报错原因是“No Such File...”之类的,找不到的文件是Pywebio和Pyecharts里的东西,我也不管到底是什么了,就直接把这两个库copy到缺失的地方,然后再运行,就终于完事大吉啦!
手动Copy补充的文件夹如上所示~
至此才终于走到Final...
3 结语
从写好这个小脚本到打包成可执行文件花了三天左右的时间,其中几乎一半都花在打包上,真可谓血泪满满,菜又爱玩。
目前的项目还很不成熟,下一步的完善方向是:
- 对脚本功能进行扩展。目前可以做的任务只是简单的分板块统计市值,以后还可以有更多方向,对有需求的画图任务还可以增加,具体的有灵感再说~
- 对代码和函数进行整理,争取写的更精炼~
- 试试看能不能减小打包后的体积~
- 尝试线上发布,这样大家就都可以使用我的小脚本啦,但笔者不懂网络这些,尚且不知道难度如何,总之先挖个坑吧~
最后希望疫情早点过去,世界和平~
Reference
【1】字母和数字分列:https://www.coder.work/article/2020734
【2】字母和数字分列:https://stackoverflow.com/questions/56672613/separate-string-from-numeric-in-single-pandas-dataframe-column-and-create-two-ne
【3】带百分比的柱状图,数据规整:https://blog.csdn.net/seakingx/article/details/105135110
【4】打包:https://github.com/pywebio/PyWebIO/issues/22
【5】打包:https://zhuanlan.zhihu.com/p/459009973
基于Webio交互的Pyecharts数据分析脚本小记相关推荐
- 基于大数据重庆市气象数据分析 计算机毕设源码24928
摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题.针对气象数据等问题,对气象 ...
- clickhouse 航空数据_趣头条基于Flink+ClickHouse的实时数据分析平台
原标题:趣头条基于Flink+ClickHouse的实时数据分析平台 分享嘉宾:王金海 趣头条 编辑整理:王彦 内容来源:Flink Forward Asia 出品平台:DataFunTalk 导读: ...
- java 脚本语言交互_Java学习笔记--脚本语言支持API
Java语言的动态性之脚本语言支持API 随着Java平台的流行,很多的脚本语言(scripting language)都可以运行在Java虚拟机啊上,其中比较流行的有JavaScript.JRuby ...
- mysql数据生产数据分析_基于MySQL玩转SQL数据分析课程 互联网数据分析师-SQL数据分析实战视频教程...
基于MySQL玩转SQL数据分析课程 互联网数据分析师-SQL数据分析实战视频教程 课程目录 (1)SQL与数Ju分析;目录中文件数:23个 (1) 开课-课时3SQL与数Ju库的价值.flv (2) ...
- python交通调查数据处理_GitHub - unlimitbladeworks/traffic-monitor: 基于高德地图的交通数据分析...
traffic-monitor(基于高德地图的交通数据分析) 设计需求在于每天上班早高峰期,每次都提前出门,虽然有地图可以实时查看路况,但是再过一阵时间 就会异常的堵车如果通过数据监控分析每天指定路段 ...
- python微信好友分析_基于python实现微信好友数据分析(简单)
一.功能介绍 本文主要介绍利用网页端微信获取数据,实现个人微信好友数据的获取,并进行一些简单的数据分析,功能包括: 1.爬取好友列表,显示好友昵称.性别和地域和签名, 文件保存为 xlsx 格式 2. ...
- 【数据可视化】基于Streamlit制作的时间序列数据分析APP(上手简单,附可运行源码)
基于Streamlit制作的时间序列数据分析APP 1.为什么要使用Streamlit(官网介绍链接) 在数据科学领域,一方面,当我们在学习或者实践机器学习算法的时候,需要进行一些参数调整:另一方面, ...
- 第1天 | 3天搞定Pyecharts数据分析,语法篇
ECharts,是遵循Apache-2.0开源协议,可免费商用的商业级数据图表,是百度使用纯Javascript实现的一个图表库.它可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器,底层依赖轻 ...
- R语言泊松回归模型案例:基于AER包的affair数据分析
R语言泊松回归模型案例:基于AER包的affair数据分析 目录 R语言泊松回归模型案例基于AER包的affair数据分析 #数据加载
最新文章
- MOS管电源开关电路的软启动
- 浅谈 Python 的 with 语句
- 【知识星球】猫猫狗狗与深度学习那些事儿
- Maven2的配置文件settings.xml
- log4j2 无日志记录_在Log4j2中更好地执行非日志记录器调用
- 微软面试题:有100万个数字(1到9),其中只有1个数字重复2次,如何快速找出该数字
- Linux Windows下忘记mysql超级管理员root密码的解决办法
- Android 开发之 fill_parent、wrap_content和match_parent的区别
- UNIX环境高级编程——记录上锁(fcntl函数)以及死锁检测
- android 蓝牙通讯测试工具,Android Bluetooth 学习(2)应用层实现蓝牙设备查找、tcp_ip通信...
- logback介绍和配置详解
- 较低成本的ISO7637-2 5A 5B抛负载保护方案
- c语言对英文字母循环加密,加密英语
- esp8266智能开关灯制作教程
- EIA/TIA布线标准(568A、568B)
- matlab 如何将.m文件所在的路径设置为当前活动目录(当前文件夹),以及保存到matlab搜索路径
- 嵌入式Qt-做一个秒表
- 计算机职业价值观测评报告,职业价值观分析测试结果
- dom4j-BackedList排序问题
- Java多线程 信号量和屏障实现控制并发线程数量,主线程等待所有线程执行完毕1
热门文章
- idea快速开发之代码块编辑
- Windows驱动开发入门 -- HelloWorld
- 卷积满足交换律:F*G(x)=G*F(x)
- 顺序表元素的多种删除方式——删除重复元素和删除掉所有相同元素
- 数学建模常用方法 | matlab代码 | 二十三种数学建模方法 |2022赛前突击 |模型代码 |比赛比用、简单高效| 分享
- 打印机系列之立象X-1000VL条码打印机的安装和使用说明总结
- iPhone设置整点报时提醒
- 特征选择数据集——不定期更新
- 拓嘉辰丰电商:多多国际入驻,需要什么资质条件
- 计算机网络之TCP三次握手