2015-08-27 8 views
15

Sarebbe bello poter visualizzare e nascondere le linee in modo interattivo in un grafico bokeh. Di ', ho creato la mia trama qualcosa di simile:Come visualizzare e nascondere le linee in modo interattivo in un grafico Bokeh?

from bokeh.plotting import output_file, figure, show 
from numpy.random import normal, uniform 

meas_data_1 = normal(0, 1, 100) 
meas_data_2 = uniform(-0.5, 0.5, 100) 

output_file("myplot.html", title="My plot") 
fig = figure(width=500, plot_height=500) 

fig.line(x=range(0, len(meas_data_1)), y=meas_data_1) 
fig.line(x=range(0, len(meas_data_2)), y=meas_data_2) 

show(fig) 

Come posso aggiungere la possibilità di abilitare in modo interattivo/disabilitare una delle due linee?

So che questo è nella lista dei desideri (vedi this feature request), ma non sembra che sarebbe stato implementato troppo presto.

Ho l'impressione che questo dovrebbe essere possibile utilizzando un CheckBoxGroup e un self-defined callback, ma purtroppo questo callback deve essere scritto in JavaScript, che non ho assolutamente alcuna esperienza in.

risposta

12

EDIT: Interactive leggende sono ora costruiti nella libreria a partire dal Bokeh 0.12.5, vedere https://bokeh.github.io/blog/2017/4/5/release-0-12-5/


Questo sembra sulla buona strada per essere implementato ad un certo punto come leggende interattive: https://github.com/bokeh/bokeh/issues/3715

Attualmente (v0.12.1), esiste un esempio che utilizza CustomJS sulle caselle di controllo per ottenere ciò: https://github.com/bokeh/bokeh/pull/4868

codice rilevante:

import numpy as np 

from bokeh.io import output_file, show 
from bokeh.layouts import row 
from bokeh.palettes import Viridis3 
from bokeh.plotting import figure 
from bokeh.models import CheckboxGroup, CustomJS 

output_file("line_on_off.html", title="line_on_off.py example") 

p = figure() 
props = dict(line_width=4, line_alpha=0.7) 
x = np.linspace(0, 4 * np.pi, 100) 
l0 = p.line(x, np.sin(x), color=Viridis3[0], legend="Line 0", **props) 
l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], legend="Line 1", **props) 
l2 = p.line(x, np.tan(x), color=Viridis3[2], legend="Line 2", **props) 

checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"], 
         active=[0, 1, 2], width=100) 
checkbox.callback = CustomJS(args=dict(l0=l0, l1=l1, l2=l2, checkbox=checkbox), 
          lang="coffeescript", code=""" 
l0.visible = 0 in checkbox.active; 
l1.visible = 1 in checkbox.active; 
l2.visible = 2 in checkbox.active; 
""") 

layout = row(checkbox, p) 
show(layout) 
+0

Grazie per la modifica! Domanda a parte: c'è un modo per farlo usando un elenco di riproduttori invece di variabili separate? Mi piacerebbe mostrare/nascondere un insieme di ~ 30 diversi renderer contemporaneamente. – user2561747

+0

Probabilmente, dovresti essere in grado di passare un elenco come uno dei valori nel dict 'args', IIRC. – bigreddot

+0

Impossibile ottenere che funzioni, bokeh sollevato 'ValueError: previsto un elemento di Dict (String, Instance (Model)), ottenuto {'renderers': [, .. .], 'checkbox': } ' – user2561747

2

Posso sbagliarmi, ma a me sembra che non v'è alcun id disponibile per le varie linee, in un modo di nasconderli sarebbe stata quella di fare un document.getElementById("idSelected").style.visibility = "hidden";

dal CheckBoxGroup non hai richiamata disposizione ho deciso di utilizzare un Select. posso ottenere la sorgente selezionata nel CustomJS, ma questo è praticamente tutto:

from bokeh.io import vform 
from bokeh.models import CustomJS, ColumnDataSource, Select 
from bokeh.plotting import output_file, figure, show 
from numpy.random import normal, uniform 

meas_data_1 = normal(0, 1, 10) 
meas_data_2 = uniform(-0.5, 0.5, 10) 

x1 = range(0, len(meas_data_1)) 
y1 = meas_data_1 
source1 = ColumnDataSource(data=dict(x=x1, y=y1)) 
x2 = range(0, len(meas_data_2)) 
y2 = meas_data_2 
source2 = ColumnDataSource(data=dict(x=x2, y=y2)) 



output_file("myplot.html", title="My plot") 
fig = figure(width=500, plot_height=500) 

fig.line('x', 'y', source=source1, line_width=3, line_alpha=0.6) 
fig.line('x', 'y', source=source2, line_width=3, line_alpha=0.6) 

select = Select(title="Option:", options=["source1", "source2"]) 

select.callback = CustomJS(args=dict(source1=source1, source2=source2, select=select), code=""" 

     console.log(select.attributes.value); 
    """) 



show(vform(fig, select)) 

Forse si può "modificare" i dati nel CustomJS rendendo ancora 0 a seconda di ciò che viene selezionato, o forse se potete accedere alla proprietà line_width e renderlo 0, ma questo è praticamente tutto ciò che riesco a pensare.

+0

Ci scusiamo per il downvote, la nuova risposta ri '0.12.1' riflette le informazioni/più attuali nuove caratteristiche per rendere questo molto più semplice. – bigreddot

Problemi correlati