2016-03-20 6 views
5

Ich bewerte Bokeh, um zu sehen, ob es für eine umfangreichere Nutzung bereit ist. Ich habe zwei Spalten eines Datenrahmens (Code am Ende), "Close" und "Adj Close" gezeichnet. enter image description hereBokeh widget-Working Checkbox Gruppe Beispiel

Ich möchte Kontrollkästchen aktivieren, um die Anzeige der beiden Liniendiagramme im Diagramm umzuschalten. Wenn das entsprechende Kontrollkästchen deaktiviert ist, wird die Zeile nicht angezeigt. Die Bokeh-Dokumentation unter http://bokeh.pydata.org/en/latest/docs/user_guide/interaction.html spricht zwar von einer Checkbox-Gruppe, bietet aber kein explizit funktionierendes Beispiel. Ich würde jede mögliche Hilfe dafür schätzen, Checkboxen zu bekommen, die für Spalten eines Datenrahmens arbeiten.

import pandas as pd 
from bokeh.plotting import figure, output_file, show 

IBM = pd.read_csv(
     "http://ichart.yahoo.com/table.csv?s=IBM&a=0&b=1&c=2011&d=0&e=1&f=2016", 
     parse_dates=['Date']) 

output_file("datetime.html") 

p = figure(width=500, height=250, x_axis_type="datetime") 

p.line(IBM['Date'], IBM['Close'], color='navy', alpha=0.5) 
p.line(IBM['Date'], IBM['Adj Close'], color='red', alpha=0.5) 

show(p) 

Antwort

1

Ich konnte die Kontrollkästchen noch nicht aktivieren, obwohl ich nicht überrascht wäre, wenn diese Funktionalität bald kommt. In der Zwischenzeit ist hier eine Abhilfe, die Multiselect-Widget mit:

from bokeh.io import vform 
from bokeh.models import CustomJS, ColumnDataSource, MultiSelect 
from bokeh.plotting import figure, output_file, show 
import pandas as pd 

IBM = pd.read_csv(
     "http://ichart.yahoo.com/table.csv?s=IBM&a=0&b=1&c=2011&d=0&e=1&f=2016", 
     parse_dates=['Date']) 

output_file("datetime.html") 
source = ColumnDataSource({'x': IBM['Date'], 'y1': IBM['Close'], \ 
'y2': IBM['Adj Close'], 'y1p': IBM['Close'], 'y2p': IBM['Adj Close']}) 

p = figure(width=500, height=250, x_axis_type="datetime") 

p.line('x', 'y1', source=source, color='navy', alpha=0.5) 
p.line('x', 'y2', source=source, color='red', alpha=0.5) 

callback = CustomJS(args=dict(source=source), code=""" 
     var data = source.get('data'); 
     var f = cb_obj.get('value') 
     y1 = data['y1'] 
     y2 = data['y2'] 
     y1p = data['y1p'] 
     y2p = data['y2p'] 
     if (f == "line2") { 
      for (i = 0; i < y1.length; i++) { 
       y1[i] = 'nan' 
       y2[i] = y2p[i] 
      } 
     } else if (f == "line1") { 
      for (i = 0; i < y2.length; i++) { 
       y1[i] = y1p[i] 
       y2[i] = 'nan' 
      } 
     } else if (f == "none") { 
      for (i = 0; i < y2.length; i++) { 
       y1[i] = 'nan' 
       y2[i] = 'nan' 
      } 
     } else { 
      for (i = 0; i < y2.length; i++) { 
       y1[i] = y1p[i] 
       y2[i] = y2p[i] 
      } 
     } 
     source.trigger('change'); 
    """) 

multi_select = MultiSelect(title="Lines to plot:", \ 
value=["line1", "line2", "none"], \ 
options=["line1", "line2", "none"], callback=callback) 
layout = vform(multi_select, p) 
show(layout) 

Die Ausgabe sieht wie folgt aus: enter image description here

+0

Danke für das Beispiel. Ich kann grob sehen, wie man das auf einen Datenrahmen mit einer beliebigen Anzahl von Spalten ausdehnt. Erstellen Sie eine Liste generierter ID-Zeichenfolgen für die ColumnDataSource. Führen Sie dann ein string.format() aus, um die Zeichenfolgen in CustomJS zu verbinden, die ebenfalls erweitert werden müssen. Wenn man sich das Gesamtbild anschaut, scheint es, dass Bokeh einige Funktionen von Plotly fehlt, aber auch hier fehlen ein paar Dinge. Die Python-Javascript-Schnittstelle ist problematisch. Ich bin versucht, reine JS-Lösungen zu untersuchen, die JSON-Dateien unterstützen, die von Python generiert wurden. – Spinor8

+1

Ja, diese Antwort skaliert nicht sehr elegant für eine größere Anzahl von Zeilen. Größeres Bild, ich stimme zu, dass Bokeh bis jetzt ein bisschen begrenzt scheint, aber ich habe nur eine Weile damit gespielt, also hoffe ich, dass es sich mit der Zeit verbessert. Ich denke, die Entwicklung von reinem JS würde sich definitiv auszahlen für jemanden, der eine Menge von dieser Art von Sache macht - vielleicht einen Beitrag zu Bokeh ?! – Peter

4

Dies ist offensichtlich eine späte Antwort, aber ich versuche derzeit Python und Bokeh zu lernen hack out eine Art von Daten-Dashboard. Ich versuchte herauszufinden, wie die Checkboxen funktionierten, und ich stolperte über Ihre Frage. Diese Lösung funktioniert nur mit Bokeh Serve. Ich weiß nicht, wie es in einer HTML-Ausgabe funktioniert.

Ich ändere nur die Sichtbarkeit der Zeile und nicht die Quelle. Ich habe es noch nicht versucht, aber ich bin sicher, dass die Legenden immer noch die unsichtbaren Linien zeigen würden.

Entschuldigung für den Klebebandcode.

#-| bokeh serve 
#-| 

import pandas as pd 
from bokeh.io import curdoc,output_file, show 
from bokeh.layouts import row, widgetbox 
from bokeh.plotting import figure 
from bokeh.models import ColumnDataSource 
from bokeh.models.widgets import * 

#Widgets 

ticker = TextInput(title='Ticker Symbol',value='IBM') 
button=Button(label='Lookup',button_type='success') 
log = Paragraph(text="""log""", 
width=200, height=100) 
cb_group = CheckboxButtonGroup(labels=['Close', 'Adj Close'],active=[0,1]) 
cb_group.labels.append('Placebo') 

#Plot 

p = figure(title='',width=500, height=250, x_axis_type='datetime') 

source = ColumnDataSource({'x': [], 'y1': [],'y2': []}) 

lineClose=p.line('x','y1',source=source, color='navy', alpha=0.5) 
lineAdj=p.line('x','y2',source=source, color='red', alpha=0.5) 

lines=[lineClose,lineAdj] 

#Event handling 

def error(msg): 
    log.text=msg 

def update_data(): 
    try: 
     src='http://ichart.yahoo.com/table.csv?s={symb}&a=0&b=1&c=2011&d=0&e=1&f=2016'.format(symb=ticker.value) 
     df=pd.read_csv(src,parse_dates=['Date']) 
     source.data=({'x': df['Date'], 'y1': df['Close'],'y2': df['Adj Close']}) 
    except: 
     error('Error ticker') 

def update_plot(new): 

    switch=cb_group.active 
    for x in range(0,len(lines)): 
     if x in switch: 
      lines[x].visible=True 
     else: 
      lines[x].visible=False 

    error('<CheckboxButtonGroup>.active = '+str(switch)) 

button.on_click(update_data) 
cb_group.on_click(update_plot) 


inputs=widgetbox(ticker,button,cb_group,log) 

curdoc().add_root(row(inputs,p,width=800)) 
curdoc().title = 'Bokeh Checkbox Example' 
button.clicks=1 

Ich habe die Checkbox ‚Placebo‘, um zu sehen, ob ich anstelle der typischen Methode der Checkbox Gruppe anhängen könnte, damit ich bin sicher, dass ein Weg, gibt es Kontrollkästchen, um mehr elegant und dynamisch hinzufügen.

what it should look like