2013-08-12 12 views
8

Sto provando a creare un programma interattivo che utilizzi principalmente matplotlib per creare grafici a dispersione piuttosto di molti punti (10k-100k o giù di lì). In questo momento funziona, ma i cambiamenti richiedono troppo tempo per essere visualizzati. Un piccolo numero di punti va bene, ma una volta che il numero sale le cose diventano frustranti di fretta. Quindi, sto lavorando per accelerare la dispersione, ma non ho molta fortunaAccelerazione di grafici scatter matplotlib

C'è il modo ovvio di fare cosa (il modo in cui è implementato ora) (mi rendo conto che la trama si ridisegna senza aggiornare. non volevo alterare il risultato fps con grandi chiamate a caso).

import matplotlib.pyplot as plt 
import numpy as np 
import matplotlib as mpl 
import time 


X = np.random.randn(10000) #x pos 
Y = np.random.randn(10000) #y pos 
C = np.random.random(10000) #will be color 
S = (1+np.random.randn(10000)**2)*3 #size 

#build the colors from a color map 
colors = mpl.cm.jet(C) 
#there are easier ways to do static alpha, but this allows 
#per point alpha later on. 
colors[:,3] = 0.1 

fig, ax = plt.subplots() 

fig.show() 
background = fig.canvas.copy_from_bbox(ax.bbox) 

#this makes the base collection 
coll = ax.scatter(X,Y,facecolor=colors, s=S, edgecolor='None',marker='D') 

fig.canvas.draw() 

sTime = time.time() 
for i in range(10): 
    print i 
    #don't change anything, but redraw the plot 
    ax.cla() 
    coll = ax.scatter(X,Y,facecolor=colors, s=S, edgecolor='None',marker='D') 
    fig.canvas.draw() 
print '%2.1f FPS'%((time.time()-sTime)/10) 

che dà un veloce 0,7 fps

In alternativa, posso modificare la collezione restituita da dispersione. Per questo, posso cambiare colore e posizione, ma non so come cambiare la dimensione di ogni punto. Che sarebbe Penso aspetto qualcosa di simile

import matplotlib.pyplot as plt 
import numpy as np 
import matplotlib as mpl 
import time 


X = np.random.randn(10000) #x pos 
Y = np.random.randn(10000) #y pos 
C = np.random.random(10000) #will be color 
S = (1+np.random.randn(10000)**2)*3 #size 

#build the colors from a color map 
colors = mpl.cm.jet(C) 
#there are easier ways to do static alpha, but this allows 
#per point alpha later on. 
colors[:,3] = 0.1 

fig, ax = plt.subplots() 

fig.show() 
background = fig.canvas.copy_from_bbox(ax.bbox) 

#this makes the base collection 
coll = ax.scatter(X,Y,facecolor=colors, s=S, edgecolor='None', marker='D') 

fig.canvas.draw() 

sTime = time.time() 
for i in range(10): 
    print i 
    #don't change anything, but redraw the plot 
    coll.set_facecolors(colors) 
    coll.set_offsets(np.array([X,Y]).T) 
    #for starters lets not change anything! 
    fig.canvas.restore_region(background) 
    ax.draw_artist(coll) 
    fig.canvas.blit(ax.bbox) 
print '%2.1f FPS'%((time.time()-sTime)/10) 

Questo si traduce in un più lento 0,7 fps. Volevo provare a utilizzare CircleCollection o RegularPolygonCollection, in quanto ciò mi avrebbe consentito di modificare facilmente le dimensioni e non mi interessa modificare l'indicatore. Ma non posso neanche disegnare, quindi non ho idea se sarebbero più veloci. Quindi, a questo punto sto cercando idee.

+0

quale versione stai usando? – tacaswell

+1

vedi anche https://github.com/matplotlib/matplotlib/pull/2156 – tacaswell

+0

Python versione 2.7.3, matplotlib 1.2.0 – george

risposta

4

che ho passato un paio di volte, cercando di accelerare i grafici a dispersione con un gran numero di punti, variamente cercando:

  • tipi di marcatore Diversi
  • Limitazione colori
  • riducendo il set di dati
  • Usando una mappa termica/griglia al posto di un grafico a dispersione

E nessuna di queste cose ha funzionato. Matplotlib non è molto performante quando si tratta di grafici a dispersione. La mia unica raccomandazione è di usare una libreria di plottaggio diversa, anche se non ne ho trovato uno che fosse adatto. So che questo non aiuta molto, ma potrebbe farti risparmiare alcune ore di armeggiare infruttuoso.

+2

Speravo davvero che non sarebbe stata la risposta, matplotlib è estremamente conveniente. Qualche possibilità di menzionare alcune delle sostituzioni matplotlib non idonee che hai provato, quindi non posso perdere tempo a scoprire che non funzioneranno? In questo momento in cima alla mia lista di cose da provare è Chaco. – george

+0

Ho finito solo con un paio, ma abbiamo continuato a tornare a matplotlib perché è il più conveniente e ben supportato. La mia prossima porta di chiamata sarebbe rpy2 se ho bisogno di fare cose veloci come la tua domanda - R è progettato per i big data e si potrebbe supporre che i loro diagrammi siano abbastanza rapidi: http://rpy.sourceforge.net/rpy2/doc-2.2 /html/graphics.html – jozzas

+0

Consiglierei le ultime 2 opzioni. Se vuoi solo una bella presentazione visuale di un campione, non ha senso tracciare l'intera cosa. Un grafico a dispersione secondario deve essere di solito OK.In alternativa è possibile suddividere il campione e visualizzare un'immagine a grana grossa (e anche eventualmente levigata, a seconda delle necessità), cambiando colore/intensità in modo che corrisponda al valore di ciascun contenitore (o "pixel"). Ti permette di mantenere 'matplotlib' senza sottoporlo a un problema troppo grande per poterlo affrontare. –