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 结语

从写好这个小脚本到打包成可执行文件花了三天左右的时间,其中几乎一半都花在打包上,真可谓血泪满满,菜又爱玩。

目前的项目还很不成熟,下一步的完善方向是:

  1. 对脚本功能进行扩展。目前可以做的任务只是简单的分板块统计市值,以后还可以有更多方向,对有需求的画图任务还可以增加,具体的有灵感再说~
  2. 对代码和函数进行整理,争取写的更精炼~
  3. 试试看能不能减小打包后的体积~
  4. 尝试线上发布,这样大家就都可以使用我的小脚本啦,但笔者不懂网络这些,尚且不知道难度如何,总之先挖个坑吧~

最后希望疫情早点过去,世界和平~

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数据分析脚本小记相关推荐

  1. 基于大数据重庆市气象数据分析 计算机毕设源码24928

    摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题.针对气象数据等问题,对气象 ...

  2. clickhouse 航空数据_趣头条基于Flink+ClickHouse的实时数据分析平台

    原标题:趣头条基于Flink+ClickHouse的实时数据分析平台 分享嘉宾:王金海 趣头条 编辑整理:王彦 内容来源:Flink Forward Asia 出品平台:DataFunTalk 导读: ...

  3. java 脚本语言交互_Java学习笔记--脚本语言支持API

    Java语言的动态性之脚本语言支持API 随着Java平台的流行,很多的脚本语言(scripting language)都可以运行在Java虚拟机啊上,其中比较流行的有JavaScript.JRuby ...

  4. mysql数据生产数据分析_基于MySQL玩转SQL数据分析课程 互联网数据分析师-SQL数据分析实战视频教程...

    基于MySQL玩转SQL数据分析课程 互联网数据分析师-SQL数据分析实战视频教程 课程目录 (1)SQL与数Ju分析;目录中文件数:23个 (1) 开课-课时3SQL与数Ju库的价值.flv (2) ...

  5. python交通调查数据处理_GitHub - unlimitbladeworks/traffic-monitor: 基于高德地图的交通数据分析...

    traffic-monitor(基于高德地图的交通数据分析) 设计需求在于每天上班早高峰期,每次都提前出门,虽然有地图可以实时查看路况,但是再过一阵时间 就会异常的堵车如果通过数据监控分析每天指定路段 ...

  6. python微信好友分析_基于python实现微信好友数据分析(简单)

    一.功能介绍 本文主要介绍利用网页端微信获取数据,实现个人微信好友数据的获取,并进行一些简单的数据分析,功能包括: 1.爬取好友列表,显示好友昵称.性别和地域和签名, 文件保存为 xlsx 格式 2. ...

  7. 【数据可视化】基于Streamlit制作的时间序列数据分析APP(上手简单,附可运行源码)

    基于Streamlit制作的时间序列数据分析APP 1.为什么要使用Streamlit(官网介绍链接) 在数据科学领域,一方面,当我们在学习或者实践机器学习算法的时候,需要进行一些参数调整:另一方面, ...

  8. 第1天 | 3天搞定Pyecharts数据分析,语法篇

    ECharts,是遵循Apache-2.0开源协议,可免费商用的商业级数据图表,是百度使用纯Javascript实现的一个图表库.它可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器,底层依赖轻 ...

  9. R语言泊松回归模型案例:基于AER包的affair数据分析

    R语言泊松回归模型案例:基于AER包的affair数据分析 目录 R语言泊松回归模型案例基于AER包的affair数据分析 #数据加载

最新文章

  1. spring与springMVC配置扫描的问题
  2. PyQt编程之模态与非模态对话框(二)
  3. net 快速打印日志
  4. java mvc mvp mvvm_一篇文章了解架构模式:MVC/MVP/MVVM
  5. 前端基础之操作标签—文档处理
  6. Vue学习笔记(八) 组件进阶
  7. linux win7 默认启动,请教:我的grub.cfg里面的内容如下,请教怎样改代码才能让WIN7设为默认启动...
  8. tensorflow计算图_通过从头开始模仿其API来了解TensorFlow
  9. PPAS数据库备份与恢复
  10. 基于库函数STM32流水灯的实现
  11. 百度知道,每天电影资源轻松引流赚钱小项目!
  12. pythonpdf识别文字_python 提取pdf文字
  13. 正则匹配中文、繁体字、不常见中文
  14. 人工智能的现状分析和未来展望
  15. 用打比方的方法,10分钟给小白讲清楚Kubernetes
  16. C语言求N阶乘的方法
  17. 【GO】panic: reflect.Value.Interface: cannot return value obtained from unexported field or method
  18. 歌手详情页:下拉方大歌手图片
  19. [ISCC 2021]部分wp
  20. DNS递归和迭代查询

热门文章

  1. Mirror 常用组件
  2. pythonista检测内容自动点击_Pythonista中文教程:100行代码实现一款远程键盘
  3. Ae 效果快速参考:表达式控制
  4. 使用新浪微博官方API抓取微博数据(Python版)
  5. 第一弹!安排!安利10个让你爽到爆的IDEA必备插件!
  6. 通过python实现企业微信公众号链接+图文推送
  7. Verilog 相等运算符之相等和全等
  8. BLDC电机FOC控制技术学习笔记
  9. 2021年网络规划设计师论文真题
  10. java获取月末日期_Java -- 获取当前日期、当月月初日期、月末日期