使用散景在Jupyter / Python中绘制交互式饼图

时间:2017-04-13 15:17:48

标签: python-2.7 slider jupyter bokeh interactive

我是Bokeh的新手,我非常感谢帮助弄清楚如何使用Bokeh在Jupyer / Python中绘制一个简单的交互式饼图。我打算在Bokeh中使用'CustomJS with Python function',如页面底部here所述。饼图由两个带有滑块的条目组成,该滑块可以更改(v1 + v2)圆形内的一个饼'v2'的形状。我试图按照散景网站中的示例来显示与正弦图的交互性,但我无法让它与我的饼图一起工作。任何帮助将不胜感激。下面是我在Jupyter笔记本中使用的代码块。

import numpy as np
import matplotlib.pyplot as plt
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource, Slider
from bokeh.plotting import Figure, output_file, show, output_notebook
from bokeh.charts import Donut, show

#output_file('donut.html')
output_notebook()

v1=1
v2=.2
import pandas as pd
data = pd.Series([v1,v2], index = list('ab')) 
plot = Figure(plot_width=400, plot_height=400)
plot = Donut(data) 
    
    
def pie_chart(source=data,window=None,deltav=None):
    data = source.data
    v2 = deltav.value
    #v2 = data['v2']
    source.trigger('change')
    
slider = Slider(start=.1, end=1., value=.2, step=.1, title="delta-V", callback=CustomJS.from_py_func(pie_chart))
callback.args["deltav"] = slider
    
l = column(slider, plot)
show(l)

5 个答案:

答案 0 :(得分:3)

如果您想以交互方式更新内容,那么最好使用bokeh.plotting API。对于一些相当无趣的技术原因,bokeh.charts API(包括Donut)不适合需要更新内容的用例。

使用bokeh.plotting,您可以使用wedge glyph method来绘制饼图。这是一个完整的示例(使用Bokeh 0.12.5),用滑块更新饼图:

from math import pi

from bokeh.io import output_file, show
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CustomJS, Slider
from bokeh.plotting import figure

output_file("pie.html")

source = ColumnDataSource(data=dict(
    start=[0, 0.2], end=[0.2, 2*pi], color=['firebrick', 'navy']
))

plot = figure()
plot.wedge(x=0, y=0, start_angle='start', end_angle='end', radius=1,
        color='color', alpha=0.6, source=source)

slider = Slider(start=.1, end=1., value=.2, step=.1, title="delta-V")

def update(source=source, slider=slider, window=None):
    data = source.data
    data['end'][0] = slider.value
    source.trigger('change')

slider.js_on_change('value', CustomJS.from_py_func(update))

show(column(slider, plot))

enter image description here

它比Donut版本稍微冗长,但是python端和JS端的数据结构之间的关系更加清晰直接。

答案 1 :(得分:0)

所有这些建议都有帮助!非常感谢。

我回到了原来的问题。现在我想使用散景服务器执行相同的交互式绘图。我已经调整the sine plot example with sliders来生成下面的代码,用于我的圆环图问题。当我使用散景服务提供服务时,我在代码中定义“数据”时出错。我认为我很接近但却错过了一小步。

''' Present an interactive function explorer with slider widgets.

Scrub the slider to change the pie shape in the donut plot

Use the ``bokeh serve`` command to run the example by executing:

    bokeh serve donuts.py

at your command prompt. Then navigate to the URL

    http://localhost:5006/donuts

in your browser.

'''
import numpy as np

from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Slider, TextInput
from bokeh.plotting import figure
from math import pi

# Set up data
source = ColumnDataSource(data=dict(
    start=[0, 0.], end=[0., 2*pi], color=["black", "red"]
))

# Set up plot
plot = figure(x_axis_location=None, y_axis_location=None, plot_width=400, plot_height=400,)
plot.annular_wedge(x=0, y=0, start_angle='start', end_angle='end', inner_radius=.4, outer_radius=.8,
        color="color", alpha=.7, source=source)
#plot.background_fill_color = None
plot.xgrid.grid_line_color = None
plot.ygrid.grid_line_color = None

# Set up widgets
slider = Slider(start=.0, end=round(2*pi,2), value=.2, step=.1, title="delta-V")

# Set up callbacks
  
def update(attrname, old, new):
    
    # Get the current slider values
    data['end'][0] = slider.value
    source.data = dict(start=start, end=end, color=color)

for w in [slider]:
    w.on_change('value', update)


# Set up layouts and add to document
inputs = widgetbox(slider)

curdoc().add_root(row(inputs, plot, width=800))
curdoc().title = "Donut"

答案 2 :(得分:0)

我想我找到了答案。这是代码,以防它

''' Present an interactive function explorer with slider widgets.

Scrub the slider to change the pie shape in the donut plot

Use the ``bokeh serve`` command to run the example by executing:

    bokeh serve donuts.py

at your command prompt. Then navigate to the URL

    http://localhost:5006/donuts

in your browser.

'''
import numpy as np

from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Slider, TextInput
from bokeh.plotting import figure
from math import pi

# Set up data
source = ColumnDataSource(data=dict(
    start=[0, 0], end=[0., 2*pi], color=["white", "red"]
))

# Set up plot
plot = figure(x_axis_location=None, y_axis_location=None, plot_width=400, plot_height=400,)
plot.annular_wedge(x=0, y=0, start_angle='start', end_angle='end', inner_radius=.4, outer_radius=.8,
        color="color", alpha=1., source=source)
#plot.background_fill_color = None
plot.xgrid.grid_line_color = None
plot.ygrid.grid_line_color = None

# Set up widgets
slider = Slider(start=.0, end=round(2*pi,2), value=.0, step=.1, title="delta-V")

# Set up callbacks
  
def update(attrname, old, new):
    
    # Get the current slider values
    z = slider.value
    source.data = dict(start=[pi,pi+z], end=[pi+z, pi], color=["yellow", "red"])

for w in [slider]:
    w.on_change('value', update)


# Set up layouts and add to document
inputs = widgetbox(slider)

curdoc().add_root(row(inputs, plot, width=800))
curdoc().title = "Donut"

答案 3 :(得分:0)

bigreddot的代码对我不起作用。剧情显示但没有改变。这是我对可以使用它的任何人的轻微修改。

#cd file directory
#bokeh serve --show filename.py

from math import pi
from bokeh.io import curdoc
from bokeh.io import output_file, show
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CustomJS, Slider
from bokeh.plotting import figure


source = ColumnDataSource(data=dict(
    start=[0, 0.2], end=[0.2, 2*pi], color=['firebrick', 'navy']
))

plot = figure()
plot.wedge(x=0, y=0, start_angle='start', end_angle='end', radius=1,
        color='color', alpha=0.6, source=source)

slider = Slider(start=.1, end=1., value=.2, step=.1, title="delta-V")

def update(attrname, old, new):
    data = source.data
    data['end'][0] = slider.value
    source.data=data

slider.on_change('value', update)

curdoc().add_root(column(slider, plot))

答案 4 :(得分:0)

我正在使用Bokeh 1.0.4,bigreddot的答案对我不起作用。滑块实际上并不会更改绘图。我使用bigreddot的示例和this website编写了一个完整的工作答案,该答案在JupyterLab v0.27.0中对我有用。

from math import pi

from bokeh.io import show, output_notebook
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application

output_notebook() # allow inline output of figures

def modify_doc(doc):

    # create the data for the plot
    def make_data(setting):
        return ColumnDataSource(data=dict(start=[0, 0.2], end=[setting, 2*pi], color=['firebrick', 'navy']))

    # make the plot
    def make_plot(source):
        plot = figure()
        plot.wedge(x=0, y=0, start_angle='start', end_angle='end', radius=1,
                color='color', alpha=0.6, source=source)
        return plot

    # update the plot
    def update(attrname,old,new):
        setting = slider.value
        src = make_data(setting)
        source.data.update(src.data)

    # controls
    slider = Slider(start=.1, end=1., value=.2, step=.1, title="delta-V")
    slider.on_change('value',update)

    source = ColumnDataSource(data=dict(
        start=[0, 0.2], end=[0.2, 2*pi], color=['firebrick', 'navy']
        ))

    p = make_plot(source)
    layout = column(slider, p)
    doc.add_root(layout)

app = Application(FunctionHandler(modify_doc))
doc = app.create_document()
show(app,notebook_url="localhost:8888")