在Jupyter Notebook

时间:2017-04-10 12:45:30

标签: jupyter-notebook scatter-plot bokeh

我正在尝试使用交互式散景图在Jupyter笔记本中创建一个仪表板,并使用ipywidgets作为小部件来控制绘图。我的用例有点复杂,因为我想创建一个带有不同标记的图,在散点图中指定不同的组,我想让用户更改组的划分(从而更改显示在图)。

我考虑了两种不同的方法:

  1. 使用散景图表API生成带有不同标记的散点图。除非我弄错了,否则这将不允许我更新情节,而是我必须在用户的每次更改时重新创建它。

  2. 使用bokeh.plotting API自行创建地块。为此,我必须自己将数据分组,并分别自行更新每组标记的数据坐标。

  3. 我已经开始尝试第二个选项,因为我想尝试自己更新绘图而不是重新创建它。我创建了一个简单的例子,它已经为我提出了一些问题。这是代码:

    p = figure()
    s = widgets.Dropdown(options=['circle', 'square'])
    
    x = np.random.normal(size=10)
    y = np.random.normal(size=10)
    
    data = ColumnDataSource(dict(x=x, y=y))
    
    r = p.scatter(source=data, x='x', y='y', size=14)
    
    def select_value(change):
        renderers = [x for x in p.renderers if x.__view_model__ == "GlyphRenderer"]
        for r in renderers:
            p.renderers.remove(r)
        if change['new'] == 'circle':
            r = p.circle(x, y, size=14)
        else:
            r = p.square(x, y, size=14)
        push_notebook()
    
    
    s.observe(select_value, 'value')
    display(s)
    show(p, notebook_handle=True)
    

    此代码块已经无法正常工作。当我从小部件中选择“正方形”时,圆圈将被移除,但在绘图的中间只添加一个正方形,而不是在圆圈的先前位置。我尝试使用p.add_glyph函数产生相同的结果,并确保广场的数据源与圆圈的数据源相同(它是)。

    任何帮助将不胜感激! 干杯, 欧米

1 个答案:

答案 0 :(得分:0)

首先,我无法使widgets.Dropdownoptions合作,我使用bokeh.models.widgets.Select。它可能是散景版,我使用0.12.4版本。 其次,在select_value更新功能中添加字形,使用bokeh.io.push_notebook(),然后删除原始渲染器,再次bokeh.io.push_notebook()

我在其中一个单元格中:

import bokeh
import bokeh.plotting
import numpy as np
from ipywidgets import interact
bokeh.io.output_notebook()

p = bokeh.plotting.figure()
s = bokeh.models.widgets.Select(options=['circle', 'square'])

x = np.random.normal(size=10)
y = np.random.normal(size=10)

source = bokeh.models.ColumnDataSource(dict(x=x, y=y))

scatter_plot = p.scatter(source=source, x='x', y='y',color="blue",marker="circle", size=14)

def select_value(change):
    renderers = [x for x in p.renderers if x.__view_model__ == "GlyphRenderer"]
    for r in renderers:
        if change == 'circle':
            myglyph = bokeh.models.Circle(x="x",y="y",fill_color="blue", line_color="blue",size=14)
        elif change == 'square':
            myglyph = bokeh.models.Square(x="x",y="y",fill_color="blue", line_color="blue",size=14)
        r.glyph = myglyph
        p.add_glyph(source,myglyph)
        bokeh.io.push_notebook()
        p.renderers.remove(r)
        bokeh.io.push_notebook()

bokeh.io.show(p, notebook_handle=True)

创建数字:

mainfigure

在我的另一个单元格中:

interact(select_value,change=['circle', 'square']);

创建交互式工具:

interactive_tool

<强>更新

另一种方法是使用visible参数。您可以创建所需的所有标记类型,然后在不使用其他标记类型的情况下显示您的选择:

import bokeh
import bokeh.plotting
import numpy as np
from ipywidgets import interact
bokeh.io.output_notebook()

p = bokeh.plotting.figure()
s = bokeh.models.widgets.Select(options=['circle', 'square'])

x = np.random.normal(size=10)
y = np.random.normal(size=10)

source = bokeh.models.ColumnDataSource(dict(x=x, y=y))

scatter_circle = p.scatter(source=source, x='x', y='y',color="blue", marker='circle', size=14)
scatter_square = p.scatter(source=source, x='x', y='y',color="blue", marker='square', size=14)
scatter_square.visible=False
handle = bokeh.io.show(p, notebook_handle=True)

def select_value(change):
    if change == 'circle':
        scatter_circle.visible=True
        scatter_square.visible=False
    elif change == 'square':
        scatter_square.visible=True
        scatter_circle.visible=False

    bokeh.io.push_notebook(handle=handle)