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. MOS管电源开关电路的软启动
  2. 浅谈 Python 的 with 语句
  3. 【知识星球】猫猫狗狗与深度学习那些事儿
  4. Maven2的配置文件settings.xml
  5. log4j2 无日志记录_在Log4j2中更好地执行非日志记录器调用
  6. 微软面试题:有100万个数字(1到9),其中只有1个数字重复2次,如何快速找出该数字
  7. Linux Windows下忘记mysql超级管理员root密码的解决办法
  8. Android 开发之 fill_parent、wrap_content和match_parent的区别
  9. UNIX环境高级编程——记录上锁(fcntl函数)以及死锁检测
  10. android 蓝牙通讯测试工具,Android Bluetooth 学习(2)应用层实现蓝牙设备查找、tcp_ip通信...
  11. logback介绍和配置详解
  12. 较低成本的ISO7637-2 5A 5B抛负载保护方案
  13. c语言对英文字母循环加密,加密英语
  14. esp8266智能开关灯制作教程
  15. EIA/TIA布线标准(568A、568B)
  16. matlab 如何将.m文件所在的路径设置为当前活动目录(当前文件夹),以及保存到matlab搜索路径
  17. 嵌入式Qt-做一个秒表
  18. 计算机职业价值观测评报告,职业价值观分析测试结果
  19. dom4j-BackedList排序问题
  20. Java多线程 信号量和屏障实现控制并发线程数量,主线程等待所有线程执行完毕1

热门文章

  1. idea快速开发之代码块编辑
  2. Windows驱动开发入门 -- HelloWorld
  3. 卷积满足交换律:F*G(x)=G*F(x)
  4. 顺序表元素的多种删除方式——删除重复元素和删除掉所有相同元素
  5. 数学建模常用方法 | matlab代码 | 二十三种数学建模方法 |2022赛前突击 |模型代码 |比赛比用、简单高效| 分享
  6. 打印机系列之立象X-1000VL条码打印机的安装和使用说明总结
  7. iPhone设置整点报时提醒
  8. 特征选择数据集——不定期更新
  9. 拓嘉辰丰电商:多多国际入驻,需要什么资质条件
  10. 计算机网络之TCP三次握手