【问题标题】:Interaction between panel and holoviews面板和全息视图之间的交互
【发布时间】:2021-03-02 19:02:41
【问题描述】:

我正在开发一个带有holoviewspanel 的小部件——它包括读取pandas.dataFrame 并为每一列显示一条曲线。我需要的交互是能够从图中添加/删除列。 在我的实际用例中,列太多,所以我无法利用 bokeh+holoviews 已经提供的交互式图例。

我举了一个小例子,'''有点像''',但我可能做错了,因为每次与panel.widgets.MultiChoice(这显然是错了)


import holoviews as hv
import numpy as np
import pandas as pd
import colorcet as cc
import panel as pn

pn.extension()
hv.extension("bokeh")

# generate some data
def get_data():
    data = {
        "1998": np.random.rand(365),
        "1999": np.random.rand(365),
        "2000": np.random.rand(365),
        "2002": np.random.rand(365),
        "2003": np.random.rand(365),
    }
    df = pd.DataFrame(data, index=range(0, 365))
    return df

# utility to help me placing the month label around the 2nd week of each month

def split_list(a, n):
    k, m = divmod(len(a), n)
    return list(
        list(a[i * k + min(i, m) : (i + 1) * k + min(i + 1, m)]) for i in range(n)
    )


def get_ticks(df, pos):
    splitter = split_list(df.index, 12)
    months = [
        "Jan",
        "Feb",
        "Mar",
        "Apr",
        "May",
        "Jun",
        "Jul",
        "Aug",
        "Sep",
        "Oct",
        "Nov",
        "Dec",
    ]
    xticks_map = [i for i in zip([splitter[i][pos] for i in range(0, 12)], months)]
    return xticks_map

# plotting method

def get_mplot(df, cols=None):
    if cols:
        df = df[cols]
    if len(df.columns) == 0:
        print("No coumns selected")
        return None
    grid_style = {
        "grid_line_color": "black",
        "grid_line_width": 1.1,
        "minor_ygrid_line_color": "lightgray",
        "minor_xgrid_line_color": "lightgray",
        "xgrid_line_dash": [4, 4],
    }
    colors = cc.glasbey_light[: len(list(df.columns))]
    xticks_map = get_ticks(df, 15)
    multi_curve = [
        hv.Curve((df.index, df[v]), label=str(v)).opts(
            xticks=xticks_map,
            xrotation=45,
            width=900,
            height=400,
            line_color=colors[i],
            gridstyle=grid_style,
            show_grid=True,
        )
        for i, v in enumerate(df)
    ]
    mplot = hv.Overlay(multi_curve)
    return mplot


# get the data
df = get_data()

# create a multi-choice widget

years = pn.widgets.MultiChoice(
    name="Years", options=list(df.columns), margin=(0, 20, 0, 0)
)

# bind plot and multi-choice

@pn.depends(years)
def get_plot(years):
    df = get_data()
    if years:
        df = df[years]
    mplot = get_mplot(df, years)
    return mplot


pn.Column("Plot!", get_plot, pn.Row(years), width_policy="max").servable()

为方便起见,我将代码作为笔记本在线存储在一个要点上:

notebook

当我定义@pn.depends method 时,我的问题是holoviewspanel 在单元格#7(在笔记本中)之间的交互 ​​- 到目前为止,我让它工作的唯一方法是“重新加载” 每次交互时的数据……(cell_out: [#21], line [#3], in df = get_data() )如果数据开始增加,这显然会减慢整个应用程序的速度。

基本上我需要一种方法来与绘图组件进行交互,而不是在每次交互时重新执行绘图。在普通的散景中,我会编写一个连接到情节的处理程序,但这是我的理解,在holoviews+panel(因为它们是建立在散景之上的一组更高级别的库)应该有一个更简单的实现相同的方法。

您对如何避免重新加载数据集有任何提示吗?

【问题讨论】:

    标签: python bokeh holoviews panel-pyviz


    【解决方案1】:

    我认为您只需要先加载数据而不覆盖数据框,例如:

    df = get_data()
    
    @pn.depends(years)
    def get_plot(years):
        if years:
            df1 = df[years]
        mplot = get_mplot(df1, years)
        return mplot
    

    【讨论】:

    • 谢谢@rich-signell,我走了那条路-它一直有效,直到多选为“非空”-但在从多选小部件。我可能需要在绘图例程中添加更多逻辑。
    • 编辑:谢谢,@rich-signell,我走了那条路-它一直有效,直到多选为“非空”-但删除时会抛出异常(df未定义)来自多选小部件的条目。但是,按照您的代码,我尝试在绘图例程中添加更多逻辑,最终发现了问题。似乎无论我在用@pn.depends 装饰的方法中更改笔记本单元格 - 代码单元格都不会更新,获取更改的唯一方法是重新启动内核....我会添加更好的描述作为后续答案。
    【解决方案2】:

    在@rich-signell 之上构建,这也适用于从多选小部件中删除所有条目时:

    @pn.depends(years)
    def get_plot(years):
        if years:
            df1 = df[years]
            mplot = get_mplot(df1, years)
        else:
            mplot = get_mplot(df)
        return mplot
    

    但是,我面临的问题是由于我在 jupyter 笔记本中对代码进行原型设计的方式。运行时出现奇怪的行为 holoviews+panel 在 jupyter 笔记本中。我能够使用以下版本在两个不同的 jupyter 服务器上复制它

    Jupyterlab, holoviews, panel
    
    '2.2.9', '1.14.0', '0.11.0a3.post2+g5aa0c91'
    '3.0.7', '1.14.2.post2+gd235b1cb0','0.10.3'
    

    问题是应用到get_plot() 方法的更改,用@pn.depends 装饰 - 直到笔记本内核重新启动,panel 小部件才接收到更改,因此任何更改代码的尝试(也是有效的解决方案) 效果不佳,让我感到困惑。

    试图在此录音中显示问题 https://gist.github.com/epifanio/6c9827f9163de359130102a29d7f3079

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多