【问题标题】:bokeh button callback only partially working散景按钮回调仅部分工作
【发布时间】:2019-05-17 17:32:52
【问题描述】:

我正在用散景绘制一个复杂的交互式圆环图。下面的代码是这个图表的一个组件的简化。

我有一个函数可以为甜甜圈编译数据数据帧,然后将其转换为 CDS。然后将该数据绘制为环形楔形。 单选按钮组应触发切换到不同的数据帧(如 CDS),并重新绘制环形楔形字形。

提供的示例(适用于 Jupyter Lab)朝一个方向工作。最初绘制 button.active == 0 (outer_1) 时。选择 outer_2 时,图表会正确更改以绘制第二个数据帧 (cds)。

但是当按下 outer_1 按钮时,字形不会变回。回调被触发 - 随着标题的变化。但字形不会改变。

为什么在随后的按钮按下/回调中字形没有变化?

我已经阅读了一些类似的 SO 帖子,还查看了一些散景示例(天气示例 here 类似)

import pandas as pd
from math import pi

from bokeh.plotting import figure

from bokeh.layouts import column, row 
from bokeh.models.widgets import RadioButtonGroup
from bokeh.io import curdoc
from bokeh.models.sources import ColumnDataSource
from bokeh.layouts import column, row

from bokeh.plotting import show, output_notebook
output_notebook()

df = pd.DataFrame({'start':[pi/2, pi, 3*pi/2],
                   'end' :[pi/2+1.5, pi+1.5, (3*pi/2)+1.5],
                   'inner': [100,100,100],
                   'outer': [200,200,200],
                   'color':['red','green','blue']})

df_2 = pd.DataFrame({'start':[pi/2, pi, 3*pi/2],
                   'end' :[pi/2+1, pi+1, (3*pi/2)+1],
                   'inner': [100,100,100],
                   'outer': [250,300,350],
                    'color':['orange','gray','purple']})

data_1 = ColumnDataSource(data=df)
data_2 = ColumnDataSource(data=df_2)


def create_doc(doc):

    button = RadioButtonGroup(labels=["outer_1", "outer_2"], active=0)

    inputs = column(button)

    p = figure(plot_width=600, plot_height=600, title="data_1",
                   x_axis_type=None, y_axis_type=None,
                   x_range=(-300, 300), y_range=(-300, 300),
                   min_border=0, outline_line_color=None,
                   background_fill_color='white', toolbar_location="above")

    circle = p.circle(0,0, radius=100, fill_alpha=0, line_color='grey', line_alpha=0.4)

    source = [data_1, data_2][button.active]

    segments = p.annular_wedge(0,0,'inner', 'outer', 'start', 'end', color='color', alpha=0.6, source=source, name='segments')


    r = row (inputs,p)


    def callback(attr, old, new):
        if button.active == 1:
            p.title.text = 'data_2  {}'.format(button.active)
            source.data.update(data_2.data)
        elif button.active == 0:
            p.title.text = 'data_1 {}'.format(button.active)
            source.data.update(data_1.data)

    button.on_change('active', callback)

    doc.add_root(r)


show(create_doc)

glpyhs 成功更改一次,但不会再次更改,尽管更改的标题文本(在按钮按下时)表明按钮和回调继续部分工作。

【问题讨论】:

  • 请注意,这是一个非常简化的示例。在真实的app中,确定要使用的数据的筛选和选择标准比较复杂,需要用到一个pandas df。完成后,我可以将其转换为 cds(如链接的天气示例中)以进行绘图。所以我真的需要了解导致问题的这种方法到底是什么。我无法避免使用 df 作为数据的主要来源点。

标签: python python-3.x bokeh jupyter-lab


【解决方案1】:

为什么要转换为DataFrame 知道内部 ColumnDataSource 的数据是字典?以下代码适用于 Bokeh v1.1.0

from math import pi
from bokeh.plotting import figure, show, curdoc, Row, Column, output_notebook
from bokeh.models import RadioButtonGroup

output_notebook()

data1 = {'start':[pi/2, pi, 3*pi/2],
        'end' :[pi/2+1.5, pi+1.5, (3*pi/2)+1.5],
        'inner': [100,100,100],
        'outer': [200,200,200],
        'color':['red','green','blue']}

data2 = {'start':[pi/2, pi, 3*pi/2],
         'end' :[pi/2+1, pi+1, (3*pi/2)+1],
         'inner': [100,100,100],
         'outer': [250,300,350],
         'color':['orange','gray','purple']}

def create_doc(doc):

    button = RadioButtonGroup(labels=["outer_1", "outer_2"], active=0)

    p = figure(plot_width=600, plot_height=600, title="data_1",
                   x_axis_type=None, y_axis_type=None,
                   x_range=(-300, 300), y_range=(-300, 300),
                   min_border=0, outline_line_color=None,
                   background_fill_color='white', toolbar_location="above")

    circle = p.circle(0,0, radius=100, fill_alpha=0, line_color='grey', line_alpha=0.4)
    segments = p.annular_wedge(0,0,'inner', 'outer', 'start', 'end', color='color', alpha=0.6, source = data1, name='segments')

    def callback(attr, old, new):
        if button.active == 0:
            print '000'
            p.title.text = 'data_1 {}'.format(button.active)
            segments.data_source.data = data1
        elif button.active == 1:
            print '111'
            p.title.text = 'data_2  {}'.format(button.active)
            segments.data_source.data = data2 

    button.on_change('active', callback)

    inputs = Column(button)
    r = Row(inputs,p)
    doc.add_root(r)

show(create_doc)

【讨论】:

  • 这是一个大大简化的例子。实际数据框很大,选择标准很复杂。但原则就是这里所代表的 - 需要对转换为 CDS 的 df 应用更改。
  • 另外 - 上面提到的散景天气示例的链接似乎遵循类似的过程: - 使用 df 选择数据 - 将 df 转换为 CDS - 在我的示例中使用回调语法来更改绘图所以我我只是想弄清楚为什么我的例子不能像那个例子那样工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-13
  • 1970-01-01
  • 1970-01-01
  • 2018-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多