bokeh button callback only partially working

≡放荡痞女 提交于 2020-03-05 04:49:27

问题


I am plotting a complex interactive donut chart in bokeh. The code below is a simplification of a component of this chart.

I have a function which compiles a dataframe of data for the donut, and then converts it to a CDS. This data is then plotted as annular wedges. A radiobutton group should trigger a switch to a different dataframe (as CDS), and replot the annular wedge glyphs.

The example provide (for Jupyter Lab) works in one direction. When initially plotted the button.active == 0 (outer_1). When outer_2 is selected, the chart correctly changes to plot the second dataframe (cds).

But when the outer_1 button is pressed, the glyphs do not change back. The callback is triggered - as the title changes. But the glyphs do not change.

Why are the glyphs not changing in subsequent button presses / callbacks?

I've read a few similar SO posts, and also reviewed a number of bokeh examples (the weather example here is similar)

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)

The glpyhs change successfully once, but not again, although the changing title text (on button presses) indicate that the buttons & callback continue to work partially.


回答1:


Why converting to DataFrame knowing that internally the data of ColumnDataSource is a dictionary? The following code works fine for 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)



来源:https://stackoverflow.com/questions/56191083/bokeh-button-callback-only-partially-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!