日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

echarts tab切换_Python 数据可视化实战:使用 PyQt5 和 Echarts 打造股票数据看板

發布時間:2024/1/23 python 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 echarts tab切换_Python 数据可视化实战:使用 PyQt5 和 Echarts 打造股票数据看板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

月小水長一個編碼者、思考者在一篇論文中,最吸引審稿人目光的莫過于枯燥的文字間精美的圖表在一份項目路演ppt 中,酷炫的財務報表往往是打動投資人的最后一劑強心劑作為數據分析最后也是最直接的一環,數據可視化的重要性不言而喻數據可視化大致可分為兩類,一類是 excel、powerBI 這類不需要寫代碼的,另一類是需要寫代碼的;而對于 Python 來說,數據可視化框架,我個人覺得大致可以分為以下兩類(推薦程度從高到底)

1、如果對于數據交互性沒有特殊要求的話,首推 matplotlib + seaborn ,其中 matplotlib 中成熟而強大的繪圖 api 應有盡有,seaborn 相當于調色筆,修改 matplotlib 本身的主題、配色風格等;matplotlib 的另一大優勢是可以結合 pandas 快速喂入數據。

2、如果對數據交互性要求高,需要點擊圖表查看數據,首推 pyecharts;如果還喜歡二次元可愛風的話,可以用 cutecharts, cutecharts 和 pycharts 均基于百度主導的 JavaScript 可視化框架 Echarts。

可以看到,cutecharts 繪制的圖表比較 Q(顯然不能做正式數據報表和論文圖表),當鼠標懸停到天線原理這一列時,會顯示出學生 A 和 B 的成績,但是 cutecharts 生成的是一個 HTML 文件,需要用瀏覽器打開才能顯示圖表,而 Python 第三方 GUI 庫 PyQt5實現了瀏覽器組件 QtWebEngineWidgets,結合 Echarts 的 JavaScript API 就能不打開瀏覽器實現酷炫的數據交互效果。

實現效果

今天要講的主題就是使用 PyQt5+Echarts 實現股票數據看板,股票數據采集自網上公開接口,考慮到網易財經歷史數據全但有延時,Tushare 數據更新快顆粒度高但調用次數有限制,融合使用網易財經和 Tushare,爬蟲這部分代碼不是今天的主題,可以跳過,且所有代碼均已上傳,關注本公眾號并在后臺回復 股票 即可獲得所有代碼(包括爬蟲+可視化)的下載鏈接。

界面布局

如上圖所示,界面可細分為三大塊,左上角的昨日股票漲跌行情餅狀圖,右上角的展示股票排行榜的 QTabWidget 表格,以及下方的某只股票 Open-Close-High-Low折線圖。上圖中,考慮到計算量的問題,餅狀圖和表格的數據都是直接偽造的,只有股票的折線圖數據是真實的。整個界面繼承自 QMainWindow,最外層的布局是豎直布局 QVBoxLayout,它包含界面上部分的 QHBoxLayout 和下方的 QHBoxLayout,并同時設置這兩個 QHBoxLayout 的 拉伸因子為 1,這樣就能夠實現上下部分等分整個界面并大小隨界面自適應改變,其語法格式是vbox?=?QVBoxLayout()
vbox.addLayout(QHBoxLayout())
vbox.addLayout(QHBoxLayout())
#?第一個參數表示?vbox?中組件的序號,也就是添加順序
#?第二個參數?表示組件在?vbox?中的權重
vbox.setStretch(0,1)
vbox.setStretch(1,1)從小的方面來說,左上角和下部分的布局都是 PyQt5 中的 QtWebEngineWidgets 組件,它就像一個瀏覽器,通過 QtWebEngineWidgets 調用 Echarts 中的 API,就能在 PyQt5 的界面中顯示 Echarts 各種各樣的的圖表。而右上角是一個 QTabWidget 組件,為了減少代碼之間的耦合,我單獨把它寫成一個 RightTableView 類,#?-*-?coding:?utf-8?-*-
#?author:???????????inspurer(月小水長)
#?pc_type???????????lenovo
#?create_time:??????2019/12/18?21:54
#?file_name:????????rightview.py
#?github????????????https://github.com/inspurer
#?qq郵箱????????????2391527690@qq.com
#?微信公眾號?????????月小水長(ID:?inspurer)

import?sys
from?PyQt5.QtWidgets?import?QApplication,QWidget,QVBoxLayout,QTabWidget,QLabel,QTableWidget,QAbstractItemView,QTableWidgetItem
from?PyQt5.QtCore?import?Qt

class?RightTableView(QWidget):
????def?__init__(self):
????????super().__init__()
????????self.mainLayout?=?QVBoxLayout()
????????tabWidgets?=?QTabWidget()
????????label?=?QLabel("前一日漲幅排名前十的股票詳細信息")
????????tabWidgets.addTab(label,?"漲幅排名")
????????label?=?QLabel("前一日成交量排名前十的股票詳細信息")
????????tabWidgets.addTab(label,?"成交量排名")
????????tabWidgets.currentChanged['int'].connect(self.tabClicked)???#?綁定標簽點擊時的信號與槽函數
????????self.mainLayout.addWidget(tabWidgets)
????????self.tableView?=?QTableWidget()
????????self.table?=?QTableWidget(self)
????????self.table.setColumnCount(6)
????????self.table.setSelectionBehavior(QAbstractItemView.SelectRows)??#?設置表格的選取方式是行選取
????????self.table.setSelectionMode(QAbstractItemView.SingleSelection)??#?設置選取方式為單個選取
????????self.table.setHorizontalHeaderLabels(["股票代碼",?"開盤",?"收盤",'最高','最低','成交量'])??#?設置行表頭
????????self.mainLayout.addWidget(self.table)
????????self.mainLayout.setStretch(0,1)
????????self.mainLayout.setStretch(1,12)
????????self.setLayout(self.mainLayout)
????????self.updateView()

????def?updateView(self):
????????self.table.insertRow(0)

????????stock_code?=?QTableWidgetItem("1001")
????????stock_code.setFlags(Qt.ItemIsSelectable?|?Qt.ItemIsEnabled)??
????????stock_code.setTextAlignment(Qt.AlignCenter)
????????stock_open?=?QTableWidgetItem("10.20")??
????????stock_open.setFlags(Qt.ItemIsSelectable?|?Qt.ItemIsEnabled)??
????????stock_open.setTextAlignment(Qt.AlignCenter)

????????stock_close?=?QTableWidgetItem("10.20")??
????????stock_close.setFlags(Qt.ItemIsSelectable?|?Qt.ItemIsEnabled)??
????????stock_close.setTextAlignment(Qt.AlignCenter)
????????stock_high?=?QTableWidgetItem("10.20")??
????????stock_high.setFlags(Qt.ItemIsSelectable?|?Qt.ItemIsEnabled)?
????????stock_high.setTextAlignment(Qt.AlignCenter)

????????stock_low?=?QTableWidgetItem("10.20")??
????????stock_low.setFlags(Qt.ItemIsSelectable?|?Qt.ItemIsEnabled)??
????????stock_dealNum.setFlags(Qt.ItemIsSelectable?|?Qt.ItemIsEnabled)?
????????stock_dealNum.setTextAlignment(Qt.AlignCenter)

????????self.table.setItem(0,?0,?stock_code)
????????self.table.setItem(0,?1,?stock_open)
????????self.table.setItem(0,?2,?stock_close)
????????self.table.setItem(0,?3,?stock_high)
????????self.table.setItem(0,?4,?stock_low)
????????self.table.setItem(0,?5,?stock_dealNum)

????def?tabClicked(self,index):
????????'''
????????tab?監聽事件,在此添加業務邏輯
????????'''
????????print(index)RightTableView 實現了 tab 的監聽,切換不同的 tab 可根據 index 展示不同的數據,因此,在主模塊中初始化 RightTableView 類的時候,應當給定 RightTableView 可能用到的所有數據,這樣可以避免使用 Signal 信號來進行主模塊和 RightTableView 模塊的通信。在主模塊中,通過 from rightview import RightTableView即可引入 RightTableView 布局,其中 rightview 是文件名,RightTableView 是類名,如改行代碼爆紅(實際上不影響運行),可在項目上右鍵 Mark Dircectory as -> Sources Root 解決之。

數據驅動

實際上,在三個小布局中,界面上部的兩個布局的數據均是偽造的,因為這個數據的采集及計算太過耗時

在 basic 表中,我記錄了 5000 支股票的基礎信息:股票交易所、股票發行公司、股票代碼,上部的兩個布局需要這 5000 支股票的整體數據,即 5000 支股票昨日相較于前日的跌漲幅,5000 支股票的跌漲幅度的排名,作為一個客戶端軟件,我覺得一個操作所能忍受的時延是 3 s 以內,優于接口還有速率限制,粗略計算了一下,這個過程遠遠超過了 30 s,所以我覺得可行的辦法是將這種采集和計算過程部署到服務器,通過設置定時任務執行,客戶端每次打開只需要一個簡單的 Get 請求即可立即渲染數據。而下方的股票 Open-Close-High-Low 折線圖所需數據的計算量比較小,可直接完成,用戶輸入股票發行公司,即可返回該公司發行股票的代碼,(因為我們一般記住的是股票發行公司而不是股票代碼,就行我們往往記住網站的域名而不是 ip 地址),如果數據庫中不存在代碼該股票的表(表名=發行公司_股票代碼),就新建,并抓取指定日期的數據存入該表;如果表存在但是缺少用戶想要的數據,則更新數據即可;這樣設計的好處是盡可能減少平均操作時延。再說這個用戶輸入股票發行公司,即可返回該公司發行股票的代碼,乍一看就是一個 key-value 字典,為了減少數據庫的操作,在程序初始化過程中,我們需要把 basic 表中的股票數據全部加載進內存,也就是放進字典里,但是由于一個公司可能發現很多股票,但是 Python 內置的字典 一個 key 只能對應一個 value ,我們很容易想到把 value 設計成一個列表,但是這樣破環了字典的原子性,假如后面我們新加了一個需要,根據 value 反查 key,也就是說根據股票代碼反查股票發行公司,如果設計成列表,這個反查耗時將是巨大的,考慮再三,我在不破壞字典 item 的原子性的前提下,實現了 value 可重復 dict,其本質是一個列表,列表元素為字典,核心思想是把鍵重復的item分散到不同字典,不過經過封裝,對外操作和字典一樣,下面是該可重復字典的實現#?-*-?coding:?utf-8?-*-
#?author:???????????inspurer(月小水長)
#?pc_type???????????lenovo
#?create_time:??????2019/12/2?12:25
#?file_name:????????myDict.py
#?github????????????https://github.com/inspurer
#?qq郵箱????????????2391527690@qq.com
#?微信公眾號?????????月小水長(ID:?inspurer)

class?AllowKeyRepeatDict():
????'''
????自定義允許鍵重復的字典
????其本質是一個列表,列表元素為字典,核心思想是把鍵重復的item分散到不同字典
????封裝后列表對外操作像字典
????'''
????def?__init__(self):
????????self.dictList?=?[]

????def?add(self,key,value):
????????length?=?len(self.dictList)
????????i?=?0
????????while?i????????????if?not?self.dictList[i].get(key,None):
????????????????self.dictList[i][key]?=?value
????????????????return?i
????????????i?+=?1
????????newDict?=?{}
????????newDict[key]?=?value
????????self.dictList.append(newDict)
????????return?i

????def?delete(self,key):
????????'''
????????:param?key:?根據?key?刪除所有?item
????????'''
????????length?=?len(self.dictList)
????????for?i?in?range(length):
????????????response?=?self.dictList[i].pop(key,None)
????????????if?not?response:
????????????????break
????????#?清除哪些空容器,注意從后往前刪,否則會出現下標越界
????????while?length>0:
????????????if?self.dictList[length-1]=={}:
????????????????del?self.dictList[length-1]
????????????length?-=?1


????def?query(self,key):
????????'''
????????:param?key:?查詢的健
????????:return:?由于允許鍵重復,返回形式是一個列表
????????'''
????????result?=?[]
????????length?=?len(self.dictList)
????????for?i?in?range(length):
????????????response?=?self.dictList[i].get(key,None)
????????????if?not?response:
????????????????return?result
????????????result.append(response)
????????return?result

????def?__str__(self):
????????'''
????????:return:?打印整個字典
????????'''
????????resStr?=?''
????????length?=?len(self.dictList)
????????if?length==0:
????????????return?'該字典為空'
????????for?i?in?range(length):
????????????for?k,v?in?self.dictList[i].items():
????????????????aItem?=?'key:{:<8}value:{:<8}\n'.format(k,v)
????????????????resStr?+=?aItem
????????return??resStr



if?__name__?==?'__main__':
????app?=?QApplication(sys.argv)
????mainWin?=?RightTableView()
????mainWin.show()
????sys.exit(app.exec_())

設計模式

當 QtWebEngineWidgets 需要新建一個圖表獲取句柄時,它希望屏蔽掉新建的具體細節,我們可以設計一個函數對應一種圖表來實現這個功能,但是我們又不想每次新建圖表時去找對應的函數,這個時候可以再設計一個代理函數,告訴這個代理函數我們需要怎樣的圖表即可獲取相應圖表的句柄。#?代理函數
def?getOptions(self,type):
????if?type==None?or?type=='K':
????????return?self.createKlines()
????elif?type=='Pie':
????????return?self.create_pie(v=[3000,600,5000])

#?K?圖表工具函數
def?createKlines(self):
????overlap?=?Overlap()
????for?quote?in?self.quote_data:
????????line?=?Line(quote['title'])
????????print(quote)
????????line.add('open',quote['date'],quote['open'],is_smooth=True)
????????line.add('close',quote['date'],quote['close'],is_smooth=True)
????????line.add('high',quote['date'],quote['high'],is_smooth=True)
????????line.add('low',quote['date'],quote['low'],is_smooth=True)

????????overlap.add(line)

????snippet?=?TRANSLATOR.translate(overlap.options)
????options?=?snippet.as_snippet()
????return?options
#?餅圖工具函數
def?create_pie(self,?v):
????pie?=?Pie()
????pie.add("昨日行情",['漲','平','跌'],?v,?is_label_show=True)
????snippet?=?TRANSLATOR.translate(pie.options)
????options?=?snippet.as_snippet()
????return?options? ? ? ? ? ? ? ? ? ? ? ? ? ?以上就是本次話題的所有內容,代碼開源,關注本公眾號并在后臺回復 股票即可獲得所有代碼,順祝大家元旦快樂(因為這篇文章從元旦開始寫的,笑~)

總結

以上是生活随笔為你收集整理的echarts tab切换_Python 数据可视化实战:使用 PyQt5 和 Echarts 打造股票数据看板的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。