2

从脚本(不在 jupyter 上)使用 hvplot 绘图时,通常的工作流程如下所示:

import hvplot

hvplot.hvPlot(data)
hvplot.show()

调用hvplot.show将导致打开浏览器新选​​项卡以呈现绘图。

我希望能够重用相同的浏览器选项卡在同一个图形上重新绘制,其方式类似于 matplotlibhold函数可能实现的方式。

我在文档上找不到任何关于它的内容。hvplot 支持流式传输,但在 jupyter notebook 之外使用它的开销太大。

有谁知道该怎么做?

4

1 回答 1

0

更新图形的一种方法是使用参数化类并使用 tornado PeriodicCallback,有关详细信息,请参阅parampanel-paramtornado.ioloop的文档。

from hvplot import hvPlot
import numpy as np
import pandas as pd
import param
import panel as pn
import tornado

class Plot(param.Parameterized):
    df = param.DataFrame(precedence=-1)

    def __init__(self, **params):
        super(Plot, self).__init__(**params)

        self.generate_df() # create a first random dataframe
        self.set_plot() # create a first plot with our new dataframe

        # Once the bokeh server (for serving our plot to a webpage) is started,
        # the underlying tornado server is taking control.
        # To be able to fetch (or here: generate) new data, we have to register
        # our method with the tornado ioloop.
        # To poll for new data, the PeriodicCallback can be used.
        self.cb = tornado.ioloop.PeriodicCallback(self.generate_df, 1000, .2)

        self.cb.start() # start the callback

        # self.callback.stop () ## In this example not implemented, callback runs indefinitely

    def generate_df(self):
        print('generate df')
        self.df = pd.DataFrame(np.random.randint(90,100,size=(5, 1)), columns=['1'])

    @param.depends('df', watch=True)
    def set_plot(self):
        self.plot = hvPlot(self.df)

    @param.depends('df', watch=True)
    def dashboard(self):
        return self.plot()

b = Plot(name="Plot")

app = pn.panel(b.dashboard)
server = app.show(threaded=False)

在此示例中,每次更改数据框时都会重新绘制整个图(例如,每次都会重置缩放...)。对情节外观的进一步更改将需要额外的回调。

如果只有数据发生变化,您将返回 Streams。在这里,我将从 切换hvplotholoviews,在我看来,它为 Streams 提供了一个更简单的接口(holoviews - 响应事件)。

第一种方法改为

import holoviews as hv
from holoviews.streams import Stream, param
import numpy as np
import pandas as pd
import param
import panel as pn
import tornado

# returns an hv.Overlay of hv.Curves for each column 
# in a given data frame
def interactive_df(df):
    curve_list = []

    for column in df.columns.values:
        curve_list.append(hv.Curve(df[column]))
    overlay = hv.Overlay(curve_list)

    return overlay

class Plot2(param.Parameterized):

    df = param.DataFrame(precedence=-1)
    DF = Stream.define('DF', df=df) # definition of a stream class, source is df
    streamdf = DF() # instance of the stream class 'DF'

    # stream data are provided to a dynamic map
    dmap = hv.DynamicMap(interactive_df, streams=[streamdf])

    def __init__(self, **params):
        super(Plot2, self).__init__(**params)

        self.generate_df() # create a first random dataframe
        self.set_plot() # create a first plot with our new dataframe

        self.cb = tornado.ioloop.PeriodicCallback(self.generate_df, 1000, .2)
        self.cb.start() # start the callback
        # self.callback.stop () ## In this example not implemented, callback runs indefinitely

    def generate_df(self):
        self.df = pd.DataFrame(np.random.randint(90,100,size=(100, 1)), columns=['1'])

    @param.depends('df', watch=True)
    def set_plot(self):
        self.dmap.event(df=self.df)

s = Plot2(name="Plot Stream")

app = pn.panel(s.dmap)
server = app.show(threaded=False)

由于只有数据发生变化,因此可以毫无问题地使用框缩放等。

此外:matplotlib的文档说,hold不推荐使用。

于 2019-12-04T20:10:09.503 回答