【问题标题】:Plotting fast incoming data in a rolling window在滚动窗口中绘制快速传入数据
【发布时间】:2018-01-23 21:38:16
【问题描述】:

我尝试在滚动窗口中使用 matplotlib 绘制快速数据(每秒 1-10 个数据点)。

我喜欢熊猫,因为它很简单。

我的问题是:

  1. 我的框架是否高效(关于使用 pandas,matplotlib 的“plt.draw”)?

  2. 如果循环运行了 1'000'000'000 次,数据框(self.df)是否会变得太大 --> 是否最好在某个时候删除数据收集器然后启动有一个空的数据框?但是滚动窗口的连续性呢?

  3. 该示例在一段时间后开始变得非常缓慢。是因为绘图效率低还是因为内存使用效率低

  4. 控制台显示警告:

MatplotlibDeprecationWarning:使用默认事件循环直到函数 特定于这个 GUI 实现了 warnings.warn(str, mplDeprecation)

我必须照顾它吗?

提前致谢

这是我目前所拥有的:

import numpy as np
import matplotlib.pyplot as plt; plt.ion()
import pandas as pd
import matplotlib
import matplotlib.gridspec as gridspec
plt.style.use('ggplot')
from pathlib import Path
import datetime
import matplotlib


class tradeScreen(object):

    def __init__(self):
        self.rollingWindow = 100
        self.df = pd.DataFrame(dict(time=np.NaN, bid=np.NaN, ask=np.NaN, limitBuy=np.NaN, limitSell=np.NaN, stopLoss=np.NaN), index=np.arange(self.rollingWindow))
        self.df['time'] = pd.to_datetime(self.df['time'])  # format 'time' as datetime object

        # initialise plot and line
        plt.figure()
        G = gridspec.GridSpec(2, 1)

        self.axes_1 = plt.subplot(G[0, :])
        self.axes_1.set_ylabel('First Panel')

        self.axes_2 = plt.subplot(G[1, :])
        self.axes_2.set_ylabel('Second Panel')

        self.line1, = self.axes_1.plot(self.df['time'], self.df['bid'])
        self.line2, = self.axes_1.plot(self.df['time'], self.df['ask'])
        self.line3, = self.axes_1.plot(self.df['time'], self.df['limitBuy'])
        self.line4, = self.axes_1.plot(self.df['time'], self.df['limitSell'])
        self.line5, = self.axes_2.plot(self.df['time'], self.df['stopLoss'])


    def plotter(self, tick, i):

        df = self.df
        rollingWindow = self.rollingWindow

        current_time = pd.datetime.now()

        df.loc[i, "bid"] = tick["bid"].values.item(0)
        df.loc[i, "ask"] = tick["ask"].values.item(0)
        df.loc[i, "limitBuy"] = tick["limitBuy"].values.item(0)
        df.loc[i, "limitSell"] = tick["limitSell"].values.item(0)
        df.loc[i, "stopLoss"] = tick["stopLoss"].values.item(0)
        df.loc[i, "time"] = current_time

        self.line1.set_data(pd.to_datetime(df['time'][:i].tail(rollingWindow)), df['bid'][:i].tail(rollingWindow))
        self.line2.set_data(pd.to_datetime(df['time'][:i].tail(rollingWindow)), df['ask'][:i].tail(rollingWindow))
        self.line3.set_data(pd.to_datetime(df['time'][:i].tail(rollingWindow)), df['limitBuy'][:i].tail(rollingWindow))
        self.line4.set_data(pd.to_datetime(df['time'][:i].tail(rollingWindow)), df['limitSell'][:i].tail(rollingWindow))
        self.line5.set_data(pd.to_datetime(df['time'][:i].tail(rollingWindow)), df['stopLoss'][:i].tail(rollingWindow))

        self.axes_1.autoscale_view(True, True, True)
        self.axes_1.relim()
        self.axes_2.autoscale_view(True, True, True)
        self.axes_2.relim()

        plt.draw()
        plt.pause(0.00000000000000001)


p = tradeScreen()
i = 0
for i in np.arange(300):

    # generate random data point
    t = pd.datetime.now()
    bid = np.random.rand()
    ask = np.random.rand()
    limitBuy = np.random.rand()
    limitSell = np.random.rand()
    stopLoss = np.random.rand()

    tick = pd.DataFrame(dict(time=t, bid=bid, ask=ask, limitBuy=limitBuy, limitSell=limitSell, stopLoss=stopLoss),
                        index=np.arange(1))

    p.plotter(tick, i)
    i += 1

【问题讨论】:

    标签: python pandas matplotlib plot time-series


    【解决方案1】:

    您可能想查看Animation 模块以在matplotlib 中制作动画。解释见此链接:http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/

    对于后代,该页面上的第一个示例给出了Animation 系统的要点:

    """
    Matplotlib Animation Example
    
    author: Jake Vanderplas
    email: vanderplas@astro.washington.edu
    website: http://jakevdp.github.com
    license: BSD
    Please feel free to use and modify this, but keep the above information. Thanks!
    """
    
    import numpy as np
    from matplotlib import pyplot as plt
    from matplotlib import animation
    
    # First set up the figure, the axis, and the plot element we want to animate
    fig = plt.figure()
    ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
    line, = ax.plot([], [], lw=2)
    
    # initialization function: plot the background of each frame
    def init():
        line.set_data([], [])
        return line,
    
    # animation function.  This is called sequentially
    def animate(i):
        x = np.linspace(0, 2, 1000)
        y = np.sin(2 * np.pi * (x - 0.01 * i))
        line.set_data(x, y)
        return line,
    
    # call the animator.  blit=True means only re-draw the parts that have changed.
    anim = animation.FuncAnimation(fig, animate, init_func=init,
                                   frames=200, interval=20, blit=True)
    

    使用 blitting(最后一行的blit=True)可能会提高您的性能。 但是,AFAIK matplotlib 的设计并未考虑性能,您可以查看其他更适合此任务的库,例如 PyQtGraph

    【讨论】:

    • 嗨 Diziet,非常感谢您的回复。当我运行代码时,它只返回一些错误消息 File "C:\Anaconda3\lib\site-packages\matplotlib\animation.py", line 898, in _blit_clear a.figure.canvas.restore_region(bg_cache[a]) KeyError : Traceback(最近一次调用最后):文件“C:\Anaconda3\lib\site-packages\matplotlib\backend_bases.py”,第 1305 行,在 _on_timer...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多