Estoy tratando de crear un gráfico de barras apiladas interactivo que muestre los datos para un valor de control deslizante dado. Todos los datos se almacenan en un conjunto de datos base y los datos que se muestran son un subconjunto de este conjunto de datos base. El problema al que me enfrento es que el código básicamente funciona, pero solo la primera vez que se emite un cambio.
Aquí hay un ejemplo mínimo:
from bokeh.layouts import column from bokeh.models import CustomJS, Slider from bokeh.plotting import ColumnDataSource, figure, output_file, show import pandas as pd base = pd.DataFrame({'a': [1, 2, 3, 4, 5, 6], 'b': [10, 20, 30, 40, 50, 60], 'c': ['x', 'y', 'x', 'y', 'x', 'y']}) edit = pd.DataFrame({'a': [1, 2], 'b': [10, 20], 'c': ['x', 'y']}) sbase = ColumnDataSource(data=base) sedit = ColumnDataSource(data=edit) p = figure(x_range=['x', 'y'], width=200, height=200) p.vbar_stack(stackers=['a', 'b'], x='c', width=0.9, color=['#7570b3', '#1b9e77'], source=sedit) slider = Slider(start=1, end=3, value=1, step=1, title='slider') slider_callback = CustomJS(args=dict(sbase=sbase, sedit=sedit), code=""" const sid = cb_obj.value; const bs = sbase.data; const ed = sedit.data; var ix = sid*2-2; var iy = sid*2-1; ed['a'] = [bs['a'][ix], bs['b'][ix]]; ed['b'] = [bs['a'][iy], bs['b'][iy]]; console.log(ed) console.log(sedit.data) sedit.change.emit(); console.log(sedit.data) """) slider.js_on_change('value', slider_callback) output_file('test.html') show(column(p, slider))Estoy un poco perdido porque, según los registros, los datos subyacentes cambian con las entradas posteriores, pero el gráfico aún permanece congelado.
source.change.emit es algo que probablemente debería ser interno, pero se ha mencionado algunos lugares donde actualmente es la única opción. Sin embargo, en general (incluido este caso), la mejor práctica recomendada es siempre realizar asignaciones reales para actualizar valores de propiedad completos (por ejemplo, .data ) de una sola vez, en lugar de cambiar las cosas "en el lugar".
slider_callback = CustomJS(args=dict(sbase=sbase, sedit=sedit), code=""" const sid = cb_obj.value; const bs = sbase.data; const ix = sid*2-2; const iy = sid*2-1; sedit.data = { a: [bs['a'][ix], bs['b'][ix]], b: [bs['a'][iy], bs['b'][iy]], c: bs.c } """)