如何清除Jupyter单元格中的Bokeh输出?

时间:2017-05-25 12:58:49

标签: python jupyter-notebook bokeh

我是否用新月更新下拉列表,Bokeh将不会使用第一次创建的相同数字。它会附加到现有的,这是我显然不想要的行为。我怎样才能更新相同的数字?

def group_plot(df, col_name, xlabel=None, plot_width=None, plot_height=None, n_columns=5, truncate_label=20):

    columns_labels, columns_counts = get_agg_data(df, col_name, n_columns=n_columns, truncate_label=truncate_label)

    bdf = pd.DataFrame(list(zip(columns_labels, columns_counts)), columns=[col_name, 'Amount'])

    bar = Bar(bdf,
              values='Amount',
              label=CatAttr(columns=[col_name], sort=False), agg='sum',
              xlabel=xlabel, ylabel="Amount",
              color=color(columns=col_name, palette=get_pwc_palette()),
              plot_width=plot_width, plot_height=plot_height,
              legend=False
             )

    return bar

def show_month_report(df):
    return show(
        column(
            row(
                group_plot(df, 'Col1', xlabel='Col1', plot_width=450, plot_height=300),
                group_plot(df, 'Col2', xlabel='Col2', plot_width=450, plot_height=300),
        ),
            row(group_plot(df, 'Col3', xlabel='Col3', plot_width=900, plot_height=350)),
        ),
        notebook_handle=True
    )

months_idxs = list(set(df['Created'].dt.month.tolist()))
options = dict(zip(get_months(months_idxs), months_idxs))
default = months_idxs[0]

drop = widgets.Dropdown(
    options=options,
    value=default,
    description='Month:',
)
display(drop)

# default: show plots for the first month
handle = show_month_report(full_df.loc[(full_df['Created'].dt.month == default),])

def _on_month_change(change):
    global full_df
    show_month_report(full_df.loc[(full_df['Created'].dt.month == change['new']),])
    push_notebook(handle=handle)

drop.observe(_on_month_change, names='value')

1 个答案:

答案 0 :(得分:0)

创建一个html小部件,它将保存散景图的html部分,并使用bokeh.embed.components将散景图转换为html和javascipt。

您需要注意两点:

  1. 致电display_javascript()后,您需要致电clear_output(),否则所有的javascript代码都将保留在单元格的输出中。

  2. 给图形一个修复ID,以防止散景在浏览器中保留多个图形实例。

  3. 这是一个演示:

    def call_javascript(code, delay=None):
        from IPython.display import display_javascript, clear_output    
        if delay is not None:
            code = 'window.setTimeout(function(){{{code}}}, {delay:d});'.format(code=code, delay=delay)
        display_javascript(code, raw=True)
        clear_output()
    
    import re
    from bokeh.io import show
    from bokeh.charts import Line, Bar, Area, BoxPlot
    from bokeh.embed import components
    import pandas as pd
    import numpy as np
    import ipywidgets as iw
    
    df = pd.DataFrame(np.random.randn(100, 3), columns=["A", "B", "C"])
    
    fig_settings = dict(
        id="myfig",
        plot_height=300
    )
    
    def plot_Line():
        return Line(df.cumsum(axis=0), x="index", **fig_settings)
    
    def plot_BoxPlot():
        return BoxPlot(pd.melt(df), label="variable", values="value", **fig_settings)
    
    def plot_Bar():
        return Bar(pd.melt(df), label="variable", values="value", legend=None, **fig_settings)
    
    def on_click(button):
        name = button.description
        func = globals()["plot_{}".format(name)]
        fig = func()
        fig._id = "myfig"
        script, html = components(fig)
        script = re.search(r'<script type="text/javascript">(.+?)</script>', script, flags=re.DOTALL | re.MULTILINE).group(1)
        w_html.value = html
        call_javascript(script)
    
    buttons = [iw.Button(description=label) for label in ["Line", "BoxPlot", "Bar"]]
    for button in buttons:
        button.on_click(on_click)
    w_html = iw.HTML(layout=iw.Layout(height="300px"))
    iw.VBox([iw.HBox(buttons), w_html])
    

    结果如下:

    enter image description here