<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python 如何實(shí)時(shí)繪制數(shù)據(jù)

          共 11570字,需瀏覽 24分鐘

           ·

          2020-08-04 18:45


          作者:TEDxPY
          來(lái)源:TTTEED

          提到 GUI 繪圖,大家可能第一反應(yīng)是 OpenGL 和 Matplotlib,但其實(shí)基于 Qt 平臺(tái)還有個(gè)功能強(qiáng)大的 pyqtgraph 繪圖庫(kù),不僅支持豐富的圖形種類(lèi),還能實(shí)時(shí)更新繪圖數(shù)據(jù)并進(jìn)行交互式操作。

          不同于網(wǎng)上其他文章或代碼講解,今天我們集中只關(guān)注實(shí)時(shí)繪制數(shù)據(jù)功能的實(shí)現(xiàn)。為了更精準(zhǔn)學(xué)習(xí)該 pyqtgraph 模塊功能,我們將參考官方給出的實(shí)例來(lái)邊學(xué)邊練。

          1. pyqtgraph 簡(jiǎn)介

          1.1 pyqtgraph 特點(diǎn)

          關(guān)于 pyqtgraph 與 Matplotlib 的對(duì)比,大致要點(diǎn)如下:

          1. pyqtgraph 在畫(huà)圖方面不如 Matplotlib 功能完整和成熟,但運(yùn)行更快
          2. Matplotlib 旨在繪制高質(zhì)量圖像,pyqtgraph 則主要面向數(shù)據(jù)抓取和數(shù)據(jù)分析的應(yīng)用
          3. 相比 Matplotlib,pyqtgraph 對(duì) python 和 qt 編程更親和
          4. pyqtgraph 具備更好的圖像交互、3D展示等

          1.2 pyqtgraph 安裝

          一般配合 PyQt5 使用,這些都要預(yù)先安裝好,我們這里只提 pyqtgraph 相關(guān):

          pip install pyqtgraph

          1.3 pyqtgraph 實(shí)例全集

          官方專(zhuān)門(mén)給出了一個(gè)實(shí)例集合,包含了展示與源碼,非常方便學(xué)習(xí),通過(guò)以下代碼來(lái)運(yùn)行:

          import pyqtgraph.examples
          pyqtgraph.examples.run()

          運(yùn)行后,會(huì)出現(xiàn)如下 GUI 界面今天我們主要關(guān)注實(shí)時(shí)繪制數(shù)據(jù),找到左側(cè)目錄中的 "Scrolling plots",單擊右側(cè)可以看到源碼

          雙擊或者點(diǎn)擊下方的 "Run Example" 便可展示運(yùn)行效果:

          特定截圖:

          2. 實(shí)時(shí)繪制學(xué)習(xí)

          結(jié)合著實(shí)例代碼和演示效果,我們可以看到有如下不同實(shí)時(shí)展示模式:

          • 模式1: 從 0 開(kāi)始固定 x 軸數(shù)值范圍,數(shù)據(jù)在該范圍內(nèi)向左移動(dòng)展示
          • 模式2: 數(shù)據(jù)帶著 x 軸坐標(biāo)一起向左移動(dòng)展示
          • 模式3: 固定 x 軸數(shù)值右側(cè)范圍到 0,數(shù)據(jù)左移展示
          • 模式4: 左側(cè)固定從 0 開(kāi)始,數(shù)據(jù)累積展示
          • 模式5: 數(shù)據(jù)范圍右側(cè)截止到 0,但仍可查看大于 0 范圍

          2.1  模式1: 固定 x 范圍,左移展示數(shù)據(jù)

          2.1.1 模式1效果

          模式1 效果

          2.1.2 實(shí)例1代碼

          我們可以在實(shí)例匯總的代碼中將該部分代碼抽離出來(lái),大致如下:

          import pyqtgraph as pg
          from pyqtgraph.Qt import QtCore, QtGui
          import numpy as np

          win = pg.GraphicsLayoutWidget(show=True)
          win.setWindowTitle('Scrolling Plots Mode 1')

          p1 = win.addPlot()
          data1 = np.random.normal(size=300)

          curve1 = p1.plot(data1)


          def update1():
              global data1, ptr1
              data1[:-1] = data1[1:]  # shift data in the array one sample left
              # (see also: np.roll)
              data1[-1] = np.random.normal()
              curve1.setData(data1)


          timer = pg.QtCore.QTimer()
          timer.timeout.connect(update1)
          timer.start(50)


          ## Start Qt event loop unless running in interactive mode or using pyside.
          if __name__ == '__main__':
              import sys

              if (sys.flags.interactive != 1or not hasattr(QtCore, 'PYQT_VERSION'):
                  QtGui.QApplication.instance().exec_()

          注意,模式 1 中實(shí)時(shí)繪制效果的實(shí)現(xiàn),是通過(guò)將數(shù)據(jù)列表中的數(shù)據(jù)整體左移實(shí)現(xiàn)的,關(guān)鍵語(yǔ)句就是 data1[:-1] = data1[1:],再通過(guò)計(jì)時(shí)器來(lái)綁定該左移數(shù)據(jù)的函數(shù),最終達(dá)到了展示中的數(shù)據(jù)動(dòng)態(tài)展示效果。

          2.1.3 寫(xiě)成 PlotWidget 形式

          總結(jié)下模式 1 的原理:x 坐標(biāo)數(shù)據(jù)不變化,對(duì)應(yīng)的 y 數(shù)據(jù)設(shè)置個(gè)左移變換的函數(shù),計(jì)時(shí)器信號(hào)綁定該左移數(shù)據(jù)的函數(shù),把 y 數(shù)據(jù)能實(shí)時(shí)設(shè)置到圖中即可。

          實(shí)例 1 中繪制圖的寫(xiě)法比較少見(jiàn),通常應(yīng)用是通過(guò) pyqtgraph.PlotWidget.plot() 來(lái)實(shí)現(xiàn)在控件中作圖再添加到 GUI 控件中,所以我們將采用 PlotWidget 的寫(xiě)法來(lái)實(shí)現(xiàn)模式1的繪制,代碼如下:

          __author__ = 'Ted'

          from PyQt5.Qt import *
          from pyqtgraph import PlotWidget
          from PyQt5 import QtCore
          import numpy as np
          import pyqtgraph as pq


          class Window(QWidget):
              def __init__(self):
                  super().__init__()
                  # 設(shè)置下尺寸
                  self.resize(600,600)
                  # 添加 PlotWidget 控件
                  self.plotWidget_ted = PlotWidget(self)
                  # 設(shè)置該控件尺寸和相對(duì)位置
                  self.plotWidget_ted.setGeometry(QtCore.QRect(25,25,550,550))

                  # 仿寫(xiě) mode1 代碼中的數(shù)據(jù)
                  # 生成 300 個(gè)正態(tài)分布的隨機(jī)數(shù)
                  self.data1 = np.random.normal(size=300)

                  self.curve1 = self.plotWidget_ted.plot(self.data1, name="mode1")

                  # 設(shè)定定時(shí)器
                  self.timer = pq.QtCore.QTimer()
                  # 定時(shí)器信號(hào)綁定 update_data 函數(shù)
                  self.timer.timeout.connect(self.update_data)
                  # 定時(shí)器間隔50ms,可以理解為 50ms 刷新一次數(shù)據(jù)
                  self.timer.start(50)

              # 數(shù)據(jù)左移
              def update_data(self):
                  self.data1[:-1] = self.data1[1:]
                  self.data1[-1] = np.random.normal()
                  # 數(shù)據(jù)填充到繪制曲線中
                  self.curve1.setData(self.data1)


          if __name__ == '__main__':
              import sys
              # PyQt5 程序固定寫(xiě)法
              app = QApplication(sys.argv)

              # 將綁定了繪圖控件的窗口實(shí)例化并展示
              window = Window()
              window.show()

              # PyQt5 程序固定寫(xiě)法
              sys.exit(app.exec())

          我們?cè)谧约簩?xiě)的代碼中重新設(shè)置了下窗口尺寸位置,數(shù)據(jù)還是按照實(shí)例中的寫(xiě)法來(lái)完成的。

          2.1.4 自寫(xiě)模式1效果

          自寫(xiě)模式1效果

          2.2  數(shù)據(jù)隨 x 軸一起左移

          2.2.1 模式2效果

          模式 2 動(dòng)態(tài)效果

          2.2.2 實(shí)例2代碼

          該模式代碼抽離出來(lái)大致如下:

          import pyqtgraph as pg
          from pyqtgraph.Qt import QtCore, QtGui
          import numpy as np

          win = pg.GraphicsLayoutWidget(show=True)
          win.setWindowTitle('pyqtgraph example: Scrolling Plots')


          p2 = win.addPlot()
          data1 = np.random.normal(size=300)

          curve2 = p2.plot(data1)
          ptr1 = 0


          def update1():
              global data1, ptr1
              data1[:-1] = data1[1:]  # shift data in the array one sample left

              data1[-1] = np.random.normal()

              ptr1 += 1
              curve2.setData(data1)
              curve2.setPos(ptr1, 0)


          timer = pg.QtCore.QTimer()
          timer.timeout.connect(update1)
          timer.start(50)


          if __name__ == '__main__':
              import sys

              if (sys.flags.interactive != 1or not hasattr(QtCore, 'PYQT_VERSION'):
                  QtGui.QApplication.instance().exec_()

          對(duì)比模式1代碼,此部分多了個(gè) curve2.setPos(ptr1, 0),通過(guò) Qt 官網(wǎng)中搜索查閱,setPos(x,y) 是將原點(diǎn)設(shè)置到 (x,y):

          ?

          Sets the position of the item to pos, which is in parent coordinates. For items with no parent, pos is in scene coordinates. The position of the item describes its origin (local coordinate (0, 0)) in parent coordinates.

          ?

          這樣我們可以大致理解為,通過(guò)設(shè)置坐標(biāo)系相對(duì)原點(diǎn)位置來(lái)產(chǎn)生 x 軸移動(dòng)的效果。

          2.2.3 寫(xiě)成 PlotWidget 形式

          總結(jié)下模式 2 的原理:y 數(shù)據(jù)與模式1相同,設(shè)置左移變換的函數(shù),計(jì)時(shí)器信號(hào)綁定該左移數(shù)據(jù)的函數(shù),把 y 數(shù)據(jù)能實(shí)時(shí)設(shè)置到圖中;x 數(shù)據(jù)則通過(guò) setPos() 函數(shù)隨著 y 的變化同步進(jìn)行設(shè)置,產(chǎn)生 x 軸同步移動(dòng)的效果。

          我們繼續(xù)采用 PlotWidget 的寫(xiě)法來(lái)實(shí)現(xiàn)模式2的繪制,在模式1基礎(chǔ)上添加幾行代碼即可,為作區(qū)分我們把曲線定義為 curve2:

          __author__ = 'Ted'

          from PyQt5.Qt import *
          from pyqtgraph import PlotWidget
          from PyQt5 import QtCore
          import numpy as np
          import pyqtgraph as pq


          class Window(QWidget):
              def __init__(self):
                  super().__init__()
                  # 設(shè)置下尺寸
                  self.resize(600,600)
                  # 添加 PlotWidget 控件
                  self.plotWidget_ted = PlotWidget(self)
                  # 設(shè)置該控件尺寸和相對(duì)位置
                  self.plotWidget_ted.setGeometry(QtCore.QRect(25,25,550,550))

                  # 仿寫(xiě) mode1 代碼中的數(shù)據(jù)
                  # 生成 300 個(gè)正態(tài)分布的隨機(jī)數(shù)
                  self.data1 = np.random.normal(size=300)

                  self.curve2 = self.plotWidget_ted.plot(self.data1, name="mode2")
                  self.ptr1 = 0

                  # 設(shè)定定時(shí)器
                  self.timer = pq.QtCore.QTimer()
                  # 定時(shí)器信號(hào)綁定 update_data 函數(shù)
                  self.timer.timeout.connect(self.update_data)
                  # 定時(shí)器間隔50ms,可以理解為 50ms 刷新一次數(shù)據(jù)
                  self.timer.start(50)

              # 數(shù)據(jù)左移
              def update_data(self):
                  self.data1[:-1] = self.data1[1:]
                  self.data1[-1] = np.random.normal()
                  # 數(shù)據(jù)填充到繪制曲線中
                  self.curve2.setData(self.data1)
                  # x 軸記錄點(diǎn)
                  self.ptr1 += 1
                  # 重新設(shè)定 x 相關(guān)的坐標(biāo)原點(diǎn)
                  self.curve2.setPos(self.ptr1,0)


          if __name__ == '__main__':
              import sys
              # PyQt5 程序固定寫(xiě)法
              app = QApplication(sys.argv)

              # 將綁定了繪圖控件的窗口實(shí)例化并展示
              window = Window()
              window.show()

              # PyQt5 程序固定寫(xiě)法
              sys.exit(app.exec())

          我們?cè)谧约簩?xiě)的代碼中重新設(shè)置了下窗口尺寸位置,數(shù)據(jù)還是按照實(shí)例中的寫(xiě)法來(lái)完成的。

          2.2.4 自寫(xiě)模式1效果

          自寫(xiě)模式2

          3. 小結(jié)

          今天先只簡(jiǎn)單整理這兩個(gè)較簡(jiǎn)單的實(shí)時(shí)繪制模式,給定的代碼中數(shù)據(jù)是用的隨機(jī)正態(tài)分布數(shù)據(jù),我們結(jié)合著模式 1 和 2 的實(shí)例代碼來(lái)分析其原理算法來(lái)仿寫(xiě)了常用版本的代碼。

          掌握模式 1 和模式 2 的用法后,我們便可以對(duì)更多的數(shù)據(jù)來(lái)進(jìn)行動(dòng)態(tài)展示,比如 CPU 占用率、股票實(shí)時(shí)價(jià)格等,配合著 PyQt5 的 GUI 圖形界面,那么完全可以用 Python 來(lái)寫(xiě)出看著高大上的數(shù)據(jù)可視化界面了,這個(gè)后續(xù)我們?cè)倮^續(xù)研究。

          ◆ ◆ ◆  ◆ 

          麟哥新書(shū)已經(jīng)在當(dāng)當(dāng)上架了,點(diǎn)擊下方小程序即可進(jìn)入當(dāng)當(dāng)購(gòu)買(mǎi)頁(yè)面:





          數(shù)據(jù)森麟公眾號(hào)的交流群已經(jīng)建立,許多小伙伴已經(jīng)加入其中,感謝大家的支持。大家可以在群里交流關(guān)于數(shù)據(jù)分析&數(shù)據(jù)挖掘的相關(guān)內(nèi)容,還沒(méi)有加入的小伙伴可以掃描下方管理員二維碼,進(jìn)群前一定要關(guān)注公眾號(hào)奧,關(guān)注后讓管理員幫忙拉進(jìn)群,期待大家的加入。


          管理員二維碼:


          猜你喜歡

           麟哥拼了!??!親自出鏡推薦自己新書(shū)《數(shù)據(jù)分析師求職面試指南》

           厲害了!麟哥新書(shū)登頂京東銷(xiāo)量排行榜!

           笑死人不償命的知乎沙雕問(wèn)題排行榜

           用Python扒出B站那些“驚為天人”的阿婆主!

           你相信逛B站也能學(xué)編程嗎



          點(diǎn)擊閱讀原文即可參與當(dāng)當(dāng)購(gòu)書(shū)活動(dòng)

          瀏覽 55
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国模吧一区二区三区 | 国产精品怡红院 | 色网站在线 | 99re88 | 欧美成人天堂 |