2011-02-12 17 views
13

He leído here que matplotlib es bueno en el manejo de grandes conjuntos de datos. Estoy escribiendo una aplicación de procesamiento de datos y he integrado gráficos de matplotlib en wx y he encontrado que matplotlib es TERRIBLE para manejar grandes cantidades de datos, tanto en términos de velocidad como en términos de memoria. ¿Alguien sabe una forma de acelerar (reducir la huella de memoria de) matplotlib que no sea reducir la resolución de sus entradas?¿Acelera Matplotlib?

Para ilustrar lo mal matplotlib es con la memoria consideran este código:

import pylab 
import numpy 
a = numpy.arange(int(1e7)) # only 10,000,000 32-bit integers (~40 Mb in memory) 
# watch your system memory now... 
pylab.plot(a) # this uses over 230 ADDITIONAL Mb of memory 
+7

Siempre he reducido el muestreo. ¿Por qué necesitarías tratar de representar 10M puntos en un gráfico? – Paul

+1

matplotlib es lento. Es un hecho conocido. Para qt uso el paquete guiqwt, tal vez haya algo así como para wx también. – tillsten

+1

@paul Solo quería facilitar a mis usuarios la exploración gráfica de los datos. es decir, cuando hacen zoom, no quería tener que volver a muestrear de nuevo según sus límites de zoom, ellos verían los datos reales sin importar cómo hicieron zoom/panned. –

Respuesta

4

disminución de resolución es una buena solución a este problema - el trazado de 10 millones de puntos consume un montón de memoria y el tiempo en matplotlib. Si sabe cuánta memoria es aceptable, puede disminuir la resolución en función de esa cantidad. Por ejemplo, digamos que 1M puntos de toma 23 MB de memoria adicional y usted encontrará que es aceptable en términos de espacio y tiempo, por lo tanto, usted debe disminuir la resolución para que sea siempre por debajo de los puntos 1m:

if(len(a) > 1M): 
    a = scipy.signal.decimate(a, int(len(a)/1M)+1) 
pylab.plot(a) 

o algo parecido el fragmento anterior (. lo anterior puede disminuir la resolución de forma demasiado agresiva para su gusto)

+1

Una simple aniquilación es inadecuada, y es lo que Matplotlib hace internamente hasta donde yo sé. La razón por la que no quiero simplemente diezmar es que pierdes los valores extremos en cada intervalo de diezmado. Si la señal tuviera un pico agudo dentro de un intervalo, no lo verías en la trama a menos que tuvieras mucha suerte con los intervalos. Escribí un código que hace esto de forma más inteligente, tomando los valores extremos para cada intervalo de diezmado en lugar del valor en el centro del intervalo (o borde). Estoy aceptando tu respuesta, ya que esto es en principio lo que hice. –

+4

David - si resolvieras esto de forma más inteligente, ¿te importaría compartir? Puede marcar sus propias respuestas como "resueltas" y puede obtener algunos votos ... – danodonovan

+0

@Dave: También le interesó cómo resolvió esto. –

1

estoy han interesado también por los valores extremos también, así que, antes de trazar grandes cantidades de datos, procedo de esta manera:

import numpy as np 

s = np.random.normal(size=(1e7,)) 
decimation_factor = 10 
s = np.max(s.reshape(-1,decimation_factor),axis=1) 

# To check the final size 
s.shape 

Por supuesto np.max es ju st un ejemplo de función de cálculo extremo.

P.S. Con numpy "strides tricks" debería ser posible evitar copiar datos durante la remodelación.