2016-01-24 24 views
10

Ho un app bokeh (v0.11) che produce un grafico a dispersione usando le coordinate (x, y) da un frame di dati. Voglio aggiungere interazioni in modo che quando un utente seleziona punti sulla trama o inserisca il nome di punti separati da virgole nella casella di testo (ad esempio "p55, p1234"), quei punti diventeranno rossi sul grafico a dispersione.Qual è un modo rapido e corretto per aggiornare/aggiornare i grafici nell'app del server Bokeh (0.11)?

Ho trovato un modo per realizzare questo (Strategia # 3, sotto) ma è terribilmente lento per i grandi dataframes. Penserei che ci sia un metodo migliore. Qualcuno mi può aiutare? Mi manca qualche ovvia chiamata di funzione?

  • Strategia 1 (< 1ms per 100 punti) Trapani nei dati ColumnDataSource per la trama esistono e tenta di cambiare i punti selezionati.
  • Strategia 2 (~ 70 ms per 100 punti) sovrascrive l'oggetto ColumnDataSource esistente con un oggetto ColumnDataSource appena creato.
  • Strategia 3 (~ 400ms per 100 punti) è la strategia 2 e quindi ricrea la cifra .

Il codice è depositato su pastebin: http://pastebin.com/JvQ1UpzY La porzione più rilevante è copiata di seguito.

def refresh_graph(self, selected_points=None, old_idxs=None, new_idxs=None): 
    # Strategy 1: Cherry pick current plot's source. 
    # Compute time for 100 points: < 1ms. 
    if self.strategy == 1: 
     t1 = datetime.now() 
     for idx in old_idxs: 
      self.graph_plot.data_source.data['color'][idx] = 'steelblue' 
     for idx in new_idxs: 
      self.graph_plot.data_source.data['color'][idx] = 'red' 
     print('Strategy #1 completed in {}'.format(datetime.now() - t1)) 
    else: 
     t3 = datetime.now() 
     self.coords['color'] = 'steelblue' 
     self.coords.loc[selected_points, 'color'] = 'red' 
     new_source = bkmodels.ColumnDataSource(self.coords) 
     self.graph_plot = self.graph_fig.scatter('x', 'y', source=new_source, color='color', alpha=0.6) 
     print('Strategy #3 completed in {}'.format(datetime.now() - t3)) 
    return 

Idealmente, vorrei essere in grado di utilizzare Strategia # 1, ma non sembra per consentire i punti per aggiornare all'interno del browser client.

Grazie per qualsiasi aiuto!

FYI: Sto usando RHEL 6.X

+0

Per altri interessati a questo: c'è una discussione su questo [sulla mailing list Bokeh] (https://groups.google.com/a /continuum.io/forum/#!topic/bokeh/fQcsikE2tJI) – Jake

risposta

4

Se siete lo streaming dei dati, allora c'è una risposta correlata qui: Timeseries streaming in bokeh

Se avete bisogno di aggiornare tutto in una volta, allora si può fare e il mio suggerimento è la tua strategia , che è dimostrata, ad esempio qui:

https://github.com/bokeh/bokeh/blob/master/examples/app/sliders.py

La cosa particolare da notare è che realmente dovete aggiornare tutti source.data in una volta sola. Una delle ipotesi è che tutte le colonne di un'origine dati di colonna abbiano sempre la stessa lunghezza. L'aggiornamento di singole colonne comporta il rischio di interrompere questa ipotesi, che può causare problemi. Così si desidera aggiornare tutti in una volta, con qualcosa di simile:

# Generate the new curve 
x = np.linspace(0, 4*np.pi, N) 
y = a*np.sin(k*x + w) + b 

source.data = dict(x=x, y=y) 
+0

Grazie per il consiglio! – user2700854