【问题标题】:Using bokeh to plot interactive pie chart in Jupyter/Python在 Jupyter/Python 中使用散景绘制交互式饼图
【发布时间】:2017-04-13 15:17:47
【问题描述】:

我是 Bokeh 的新手,如果我能帮助我了解如何使用 Bokeh 在 Jupyer/Python 中绘制一个简单的交互式饼图,我将不胜感激。我计划在 Bokeh 中使用“CustomJS with a 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)

【问题讨论】:

    标签: python-2.7 slider jupyter bokeh interactive


    【解决方案1】:

    如果您想以交互方式更新内容,那么最好使用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))
    

    Donut的版本略显冗长,但是python端和JS端的数据结构之间的关系要清晰直接得多。

    【讨论】:

    • 这太棒了!非常感谢您提出这个建议。我不知道 bokeh.charts 的局限性。现在,有什么办法可以去掉饼图后面的轴、网格和白色?另外,是否可以使用 bokeh.plotting 绘制圆环图(带孔的饼图)?
    • 是的,请参阅用户指南的Styling Visual Attributes 部分。对于另一个问题,是的,还有一个annular_wedge 字形方法,它同时采用内半径和外半径
    • 实际上要完全摆脱轴,您会想要figure(..., x_axis_location=None, ...),我猜这在其他地方都有记录。摆脱网格是一个样式问题(将网格线颜色设置为无)
    【解决方案2】:

    我想我找到了答案。这是代码以防万一

    ''' 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】:

      来自 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】:

        我正在使用 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")
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-16
          • 2015-10-13
          • 1970-01-01
          • 1970-01-01
          • 2019-11-24
          • 2022-08-18
          相关资源
          最近更新 更多