c# .net charts large-files zedgraph

c# - Gráficos masivos de datos



.net charts (4)

Actualmente estamos utilizando ZedGraph para dibujar un gráfico de líneas de algunos datos. Los datos de entrada provienen de un archivo de tamaño arbitrario, por lo tanto, no sabemos de antemano cuál es el número máximo de puntos de datos. Sin embargo, al abrir el archivo y leer el encabezado, podemos averiguar cuántos puntos de datos hay en el archivo.

El formato del archivo es esencialmente [tiempo (doble), valor (doble)]. Sin embargo, las entradas no son uniformes en el eje temporal. Puede que no haya puntos entre, digamos, t = 0 s y t = 10 s, pero puede haber 100 K entires entre t = 10 s y t = 11 s, y así sucesivamente.

Como ejemplo, nuestro archivo de prueba de datos es de ~ 2.6 GB y tiene 324M puntos. Nos gustaría mostrar el gráfico completo al usuario y dejar que navegue por el gráfico. Sin embargo, cargar 324M puntos en ZedGraph no solo es imposible (estamos en una máquina de 32 bits), sino que tampoco es útil, ya que no hay ningún punto en tener tantos puntos en la pantalla.

El uso de la función FilteredPointList de ZedGraph también parece estar fuera de discusión, ya que eso requiere cargar primero todos los datos y luego filtrarlos.

Entonces, a menos que nos falte algo, parece que nuestra única solución es, de alguna manera, diezmar los datos, sin embargo, a medida que seguimos trabajando en ello, nos encontramos con muchos problemas:

1- ¿Cómo diezmamos los datos que no llegan uniformemente en el tiempo?

2- Dado que no se pueden cargar todos los datos en la memoria, cualquier algoritmo debe funcionar en el disco y, por lo tanto, debe diseñarse con cuidado.

3- ¿Cómo manejamos el acercamiento y alejamiento, especialmente cuando los datos no son uniformes en el eje x?

Si los datos fueran uniformes, en la carga inicial del gráfico, podríamos Seek() por una cantidad predefinida de entradas en el archivo, y elegir todas las N otras muestras y enviarlas a ZedGraph. Sin embargo, dado que los datos no son uniformes, tenemos que ser más inteligentes al elegir las muestras para mostrar, y no podemos encontrar ningún algoritmo inteligente que no tenga que leer todo el archivo.

Me disculpo ya que la pregunta no tiene una especificidad muy clara, pero espero poder explicar la naturaleza y el alcance de nuestro problema.

Estamos en Windows de 32 bits, .NET 4.0.


1- ¿Cómo diezmamos los datos que no llegan uniformemente en el tiempo?

( Nota : supongo que el archivo de datos de su cargador está en formato de texto).

En un proyecto similar, tuve que leer archivos de datos de más de 5 GB de tamaño. La única forma en que podría analizarlo fue mediante la lectura en una tabla RDBMS. Elegimos MySQL porque hace que la importación de archivos de texto a datos de datos sea sencilla. (Un lado interesante: estaba en una máquina Windows de 32 bits y no pude abrir el archivo de texto para verlo, pero MySQL no lo leyó.) La otra ventaja es que MySQL está gritando, gritando rápido .

Una vez que los datos estuvieran en la base de datos, podríamos clasificarlos fácilmente y cuantificar grandes cantidades de datos en consultas parafraseadas singulares (utilizando funciones de resumen de SQL incorporadas como SUM ). MySQL podría incluso leer los resultados de sus consultas en un archivo de texto para usarlos como datos de carga.

En pocas palabras, consumir tanta información exige el uso de una herramienta que pueda resumir los datos. MySQL cumple con los requisitos (juego de palabras ... es gratis).


He necesitado esto antes, y no es fácil de hacer. Terminé escribiendo mi propio componente gráfico debido a este requisito. Resultó mejor al final, porque puse todas las funciones que necesitábamos.

Básicamente, necesita obtener el rango de datos (valores de índice mínimo y máximo posible / necesario), subdividir en segmentos (digamos 100 segmentos) y luego determinar un valor para cada segmento mediante algún algoritmo (valor promedio, valor de la mediana, etc.) ). Luego se grafican en base a esos 100 elementos resumidos. Esto es mucho más rápido que tratar de trazar millones de puntos :-).

Entonces lo que estoy diciendo es similar a lo que estás diciendo. Menciona que no desea trazar todos los elementos X porque puede haber un largo período de tiempo (valores de índice en el eje x) entre los elementos. Lo que estoy diciendo es que para cada subdivisión de datos determine cuál es el mejor valor y tómelo como el punto de datos. Mi método se basa en valores de índice, por lo que en su ejemplo de que no hay datos entre los valores de índice de 0 seg. Y 10 seg. Todavía pondría puntos de datos allí, solo tendrían los mismos valores entre ellos.

El punto es resumir los datos antes de trazarlos. Piense en sus algoritmos para hacerlo con cuidado, hay muchas maneras de hacerlo, elija la que funcione para su aplicación.

Podría evitarse no escribir su propio componente gráfico y simplemente escribir el algoritmo de resumen de datos.


Me acercaría a esto en dos pasos:

  1. Pre-procesamiento de los datos.
  2. Mostrando los datos

Paso 1 El archivo debe preprocesarse en un archivo de formato fijo binario. Añadiendo un índice al formato, sería int, double, double. Vea este artículo para comparaciones de velocidad:

http://www.codeproject.com/KB/files/fastbinaryfileinput.aspx

Luego puede dividir el archivo en intervalos de tiempo, digamos uno por hora o por día, lo que le dará una forma fácil de expresar el acceso a diferentes intervalos de tiempo. También puedes mantener un archivo grande y tener un archivo de índice que te indique dónde encontrar los tiempos específicos.

1,1 / 27/2011 8:30:00
13456,1 / 27/2011 9:30:00

Al utilizar uno de estos métodos, podrá encontrar rápidamente cualquier bloque de datos por tiempo, a través de un índice o nombre de archivo, o por número de entradas, debido al formato de byte fijo.

Paso 2 Formas de mostrar datos 1. Solo muestre cada registro por índice. 2. Normalice los datos y cree barras de datos agregados con valores de apertura, alto, bajo y cierre. a. Por tiempo b. Por recuento de registros c. Por diferencia entre valor

Para obtener más formas posibles de agregar conjuntos de datos no uniformes, es posible que desee ver los diferentes métodos utilizados para agregar datos comerciales en los mercados financieros. Por supuesto, para la velocidad en la representación en tiempo real, desearía crear archivos con estos datos ya agregados.


Una alternativa relativamente fácil que he encontrado para hacer esto es hacer lo siguiente:

  1. Iterar a través de los datos en pequeños grupos de puntos (por ejemplo, de 3 a 5 puntos a la vez: cuanto más grande sea el grupo, más rápido funcionará el algoritmo, pero menos precisa será la agregación).
  2. Calcula el mínimo y máximo del grupo pequeño.
  3. Elimine todos los puntos que no sean el mínimo o el máximo de ese grupo (es decir, solo mantiene 2 puntos de cada grupo y omite el resto).
  4. Continúe recorriendo los datos (repitiendo este proceso) desde el inicio hasta el final, eliminando puntos hasta que el conjunto de datos agregados tenga un número suficientemente pequeño de puntos en los que se pueda representar sin estrangular la PC.

He usado este algoritmo en el pasado para tomar conjuntos de datos de ~ 10 millones de puntos hasta el orden de ~ 5K puntos sin ninguna distorsión visible evidente en el gráfico.

La idea aquí es que, mientras arrojas puntos, estás preservando los picos y valles, por lo que la "señal" que se ve en el gráfico final no se "promedia" (normalmente, si promedias, verás los picos y la los valles se hacen menos prominentes).

La otra ventaja es que siempre se ven puntos de datos "reales" en el gráfico final (faltan muchos puntos, pero los puntos que existen en realidad estaban en el conjunto de datos original, por lo tanto, si pasa el mouse sobre algo, puede mostrar el los valores reales de x e y porque son reales, no promediados).

Por último, esto también ayuda con el problema de no tener un espaciado consistente del eje x (de nuevo, tendrá puntos reales en lugar de promediar las posiciones del eje X).

No estoy seguro de qué tan bien funcionaría este enfoque con cientos de millones de puntos de datos como usted, pero vale la pena intentarlo.