wolfram mathematica - two - Acelera ListLinePlot
plot options mathematica (4)
Estoy tratando de usar Mathematica para analizar algunos datos sin procesar. Me gustaría poder mostrar dinámicamente el rango de datos que me interesan usando Manipulate
y ListLinePlot
, pero la representación de la gráfica es extremadamente lenta. ¿Cómo puedo acelerarlo?
Aquí hay algunos detalles adicionales. Un archivo de texto externo almacena los datos sin procesar: la primera columna es una marca de tiempo, la segunda, tercera y cuarta columnas son lecturas de datos, por ejemplo:
1309555993069, -2.369941, 6.129157, 6.823794
1309555993122, -2.260978, 6.170018, 7.014479
1309555993183, -2.070293, 6.129157, 6.823794
1309555993242, -1.988571, 6.238119, 7.123442
Un solo archivo de datos contiene hasta 2 · 10 6 líneas. Para mostrar, por ejemplo, la segunda columna, utilizo:
x = Import["path/to/datafile"];
ListLinePlot[x[[All, {1, 2}]]]
El tiempo de ejecución de esta operación es insoportablemente largo. Para mostrar un rango variable de datos intenté usar Manipulate
:
Manipulate[ListLinePlot[Take[x, numrows][[All, {1, 2}]]], {numrows, 1, Length[x]}]
Esta instrucción funciona, pero se arrastra rápidamente cuando intento mostrar más de unas mil líneas. ¿Cómo puedo acelerarlo?
Algunos detalles adicionales:
- MATLAB muestra la misma cantidad de datos en la misma computadora de forma casi instantánea, por lo que el tamaño de los datos en bruto no debería ser un problema.
- Ya traté de desactivar gráficos antialiasing, pero no afectó la velocidad de renderizado.
- Usar
DataRange
para evitarTake
no ayuda. - El uso de
MaxPlotPoints
distorsiona demasiado la trama para ser útil. - No usar
Take
inManipulate
no ayuda. - La renderización parece tomar mucho tiempo. Running
Timing[ListLinePlot[Take[x,100000][[All, {1, 2}]]]]
devuelve0.33
: esto significa que la evaluación deTake
por sí misma es casi instantánea, es la representación de la trama que ralentiza todo. - Estoy ejecutando Mathematica en Ubuntu Linux 11.10 usando los controladores fglrx. Obligar a Mathematica a usar controladores de mesa no ayudó.
¿Alguna pista?
También noté que, de vez en cuando, Mathematica tardará demasiado en representar gráficos. En realidad, debe ser un paso de traducción de una expresión de Graphics
Mathematica a otra representación que lleva mucho tiempo porque una vez procesada, redimensionado (y por lo tanto re-renderizado) el gráfico es mucho más rápido. La representación gráfica previa a la versión 6 solía ser más rápida para muchos ejemplos (pero también carece de una gran cantidad de funcionalidades con más de 6).
Algunas ideas sobre lo que podrías hacer:
Use la opción
MaxPlotPoints
deListLinePlot
para reducir los datos antes de trazar. Puede no hacer una diferencia en el aspecto si se muestrea de forma insuficiente. La opciónMethod
debe elegir el algoritmo de reducción de resolución, pero no puedo encontrar ningún documento (¿alguien?)Use
ContinuousAction -> False
enManipulate
para evitar que vuelva a calcular todo en tiempo real a medida que arrastra los controles deslizantes.
No he probado mucho esto en mi máquina (tengo una Mac, por lo que no puedo descartar problemas específicos de Linux). pero un par de puntos se me ocurren. Lo siguiente fue bastante rápido para mí, pero obviamente más lento que si el conjunto de datos fuera más pequeño. Está tramando cientos de miles de puntos de datos.
data = Accumulate@RandomVariate[NormalDistribution[], 200000];
Manipulate[ListLinePlot[Take[data, n]], {n, 1, Length[data]}]
- En un
Manipulate
, está permitiendo que la cantidad de datos mostrada conTake
varíe arbitrariamente. Intenta incrementarnumrows
cada 100 o más puntos, por lo que hay menos para renderizar. - Intente utilizar la opción
ContinuousAction->False
(consulte la documentación ) (Veo que @Szabolcs tenía la misma idea que estaba escribiendo). - Estaba a punto de sugerir
MaxPlotPoints
, pero en su lugar probé la opciónPerformanceGoal ->"Speed"
. (ver documentación )
Otra idea es usar el algoritmo Ramer-Douglas-Peucker para reducir el número de puntos de datos antes de trazar. Es probable que esto preserve la forma de los datos mejor. No sé si todavía necesita esto, así que no proporcionaré una implementación.
Si su objetivo es simplemente visualizar sus datos de manera rápida pero adecuada, puede usar el siguiente truco, que estoy usando constantemente.
Participo los datos en un número de bloques que corresponden aproximadamente a la resolución de mi pantalla (generalmente 1000 o menos), de todos modos no se pueden mostrar más detalles. Luego, determino el Mín. Y el Máx. De cada bloque y trazo una línea en zig-zag de mínimo a máximo a mínimo a máximo ... El resultado se verá exactamente como los datos originales. Sin embargo, no puede "acercarse", ya que entonces verá la línea zig-zag (por ejemplo, al exportar a alta resolución en pdf). Entonces necesitas usar una mayor cantidad de bloques.
rv = RandomVariate[ExponentialDistribution[2], 100000];
ListLinePlot[rv, PlotRange -> All] (* original, slow *)
ListLinePlot[rv, PlotRange -> All, MaxPlotPoints -> 1000] (* fast but distorted *)
numberOfBlocks = 1000;
ListLinePlot[Riffle @@ Through[{Min /@ # &, Max /@ # &}[
Partition[rv,Floor[Length[rv]/numberOfBlocks]]]], PlotRange -> All]
Puede agregar la DataRange->{...}
para etiquetar apropiadamente el eje x.
¡Espero que esto ayude!
EDITAR: Vea también esta pregunta similar en Mathematica Stackexchange: https://mathematica.stackexchange.com/q/140/58