如何在HvPlot中重用图形?

时间:2019-05-24 16:01:04

标签: python holoviews hvplot

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

import hvplot

hvplot.hvPlot(data)
hvplot.show()

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

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

我在文档上找不到任何相关内容。 hvplot支持流传输,但是在jupyter笔记本之外使用它会产生太多开销。

有人知道该怎么做吗?

1 个答案:

答案 0 :(得分:0)

更新图形的一种方法是使用参数化的类并使用龙卷风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。 在这里,我将从hvplot切换到holoviews,在我看来,这为Streams(holoviews - Responding to Events)提供了更简单的界面。

第一种方法更改为

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已过时。