2011-01-27 12 views
15

Actualmente estamos usando 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 cuál es el número máximo de puntos de datos por adelantado. Sin embargo, al abrir el archivo y leer el encabezado, podemos averiguar cuántos puntos de datos hay en el archivo.Trazando cantidades masivas de datos

El formato de archivo es esencialmente [tiempo (doble), valor (doble)]. Sin embargo, las entradas no son uniformes en el eje de tiempo. Es posible que no haya ningún punto entre digamos t = 0 sec yt = 10 seg, pero puede haber 100K entires entre t = 10 seg yt = 11 seg, y así sucesivamente.

Como ejemplo, nuestro archivo de datos de prueba es ~ 2.6 GB y tiene 324M puntos. Nos gustaría mostrar el gráfico completo al usuario y dejarla navegar a través del gráfico. Sin embargo, cargar hasta 324M puntos en ZedGraph no solo es imposible (estamos en una máquina de 32 bits), sino que tampoco es útil ya que no tiene sentido tener tantos puntos en la pantalla.

El uso de la función FilteredPointList de ZedGraph también parece estar fuera de cuestión, ya que esto requiere cargar primero todos los datos y luego realizar el filtrado de esos datos.

tanto, a menos que nos falta nada, parece que nuestra única solución es -somehow- diezmar los datos, sin embargo a medida que seguimos trabajando en ello, nos estamos quedando en un montón de problemas:

1- ¿Cómo se diezman los datos que no llegan uniformemente a tiempo?

2- Dado que no se pueden cargar todos los datos en la memoria, cualquier algoritmo debe funcionar en el disco y 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 fueron uniformes, con la carga inicial del gráfico, podríamos Seek() por cantidad predefinida de entradas en el archivo, y elegir cada N otras muestras y alimentarlo a ZedGraph. Sin embargo, dado que los datos no son uniformes, debemos 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.

Pido disculpas ya que la pregunta no tiene una especificidad nítida, pero espero poder explicar la naturaleza y el alcance de nuestro problema.

Estamos en Windows 32-bit, .NET 4.0.

Respuesta

8

Lo he necesitado 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 características que necesitábamos.

Básicamente necesita obtener el rango de datos (valores mínimos y máximos posibles/necesarios), subdividirlos en segmentos (digamos 100 segmentos), y luego determinar un valor para cada segmento mediante algún algoritmo (valor promedio, mediana valor, etc.). Luego, traza 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 dices. Usted 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 tome eso como el punto de datos. Mi método está basado en el valor del índice, por lo que en su ejemplo de ausencia de datos entre los valores de índice de 0 y 10 segundos, todavía colocaría puntos de datos allí, simplemente tendrían los mismos valores entre ellos.

El punto es resumir los datos antes de trazarlos. Analice cuidadosamente sus algoritmos para hacerlo, hay muchas maneras de hacerlo, elija el que funcione para su aplicación.

Puede salirse con la suya al no escribir su propio componente gráfico y simplemente escribir el algoritmo de resumen de datos.

+0

De acuerdo en su último punto. Resumir los datos de forma adecuada aliviará el dolor de cabeza de mostrar x # de escenarios. –

+0

gmagana: Sí, creo que suena como una manera de hacerlo. Solo me preocupa que cada vez que el usuario quiera acercarse o alejarse, tengamos que volver a leer y volver a resumir el archivo. Pensamos en algunos algoritmos de almacenamiento en caché, pero dado que en algún momento, los datos en el gráfico serán diezmados, el almacenamiento en caché de esos puntos puede no tener sentido. – SomethingBetter

+0

@SomethingBetter: Sí, el zoom es una de las razones por las que escribí el mío. Necesitábamos algo así como el gráfico de Google Finance (es decir, http://www.google.com/finance?q=msft), así que lo escribí desde cero. –

3

1- ¿Cómo podemos diezmar los datos que no son que llegan uniformemente a tiempo?

(Nota -. Estoy asumiendo que el archivo de datos cargador se encuentra en formato de texto)

en un proyecto similar, tuve que leer los ficheros de datos que eran más de 5 GB de tamaño. La única forma en que pude analizarlo fue leyéndolo en una tabla RDBMS. Elegimos MySQL porque hace que la importación de archivos de texto en datatables sea extremadamente simple. (Un aspecto interesante: estaba en una máquina con Windows de 32 bits y no pude abrir el archivo de texto para verlo, pero MySQL lo leyó sin problemas.) La otra ventaja era MySQL es gritando, gritando rápido.

Una vez que los datos estaban en la base de datos, podíamos ordenarlos fácilmente y cuantificar grandes cantidades de datos en consultas parafraseadas singulares (usando las funciones integradas de resumen SQL como SUM). MySQL incluso podría leer los resultados de su consulta de nuevo en un archivo de texto para usarlos como datos del cargador.

Para resumir, consumir tantos datos exige el uso de una herramienta que puede resumir los datos. MySQL cumple con los requisitos (juego de palabras intencionado ... es gratis).

+0

Eso es interesante, obtener todos estos datos en la base de datos primero puede ser mucho tiempo, pero creo que si vamos a analizar los mismos datos una y otra vez, podría ser útil. Sin embargo, esto no ayuda en absoluto con nuestro problema fundamental: cómo leer estos datos, resumir en un número razonable de puntos y mostrarlos en el gráfico. - Gracias – SomethingBetter

4

me acercaría esto en dos pasos:

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

Paso 1 El archivo debe ser procesada previamente en un archivo de formato fijo binario. Agregando un índice al formato, sería int, double, double. Consulta este artículo para comparaciones de velocidad:

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

A continuación, puede romper el archivo en intervalos de tiempo, digamos uno por hora o por día, lo que le dará una manera fácil de expresar acceso a tiempo diferente intervalos. También puede simplemente mantener un archivo grande y tienen un archivo de índice que le dice dónde encontrar momentos específicos,

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

mediante el uso de uno de estos métodos que serán capaces de encontrar rápidamente cualquier bloque de datos ya sea por tiempo, a través de un nombre de índice o archivo, o por el número de entradas, debido al formato fijo de bytes .

Paso 2 Maneras de mostrar los datos 1. Simplemente visualice cada registro por índice. 2. Normalice los datos y cree barras de datos agregados con valores abiertos, altos, bajos y cercanos. a. Por tiempo b.Por número de registros c. Por Diff entre el valor

Para obtener más formas posibles de agregar conjuntos de datos no uniformes, le recomendamos que consulte diferentes métodos utilizados para agregar datos comerciales en los mercados financieros. Por supuesto, para la velocidad en el procesamiento en tiempo real que desea crear archivos con estos datos ya agregado.

+0

El artículo del proyecto de código fue interesante, gracias. – SomethingBetter

0

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

  1. iterar a través de los datos de agrupaciones de puntos pequeños (por ejemplo de 3 a 5 puntos a la vez - cuanto mayor sea el grupo, más rápido funcionará el algoritmo, pero será menos precisa la agregación).
  2. Calcula el mínimo & máximo del pequeño grupo.
  3. Eliminar todos los puntos que son no el valor mínimo o máximo de ese grupo (es decir, solo conserva 2 puntos de cada grupo y omite el resto).
  4. Continúe recorriendo los datos (repitiendo este proceso) de principio a fin eliminando los puntos hasta que el conjunto de datos agregados tenga una cantidad de puntos suficientemente pequeña donde pueda ser graficado sin asfixiar la PC.

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

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

La otra ventaja es que siempre está viendo puntos de datos "reales" en el gráfico final (le faltan un montón de puntos, pero los puntos que están ahí estaban realmente en el conjunto de datos original, así que si pasa el mouse sobre algo, puede mostrar los valores reales x & 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 los que tiene, pero podría valer la pena intentarlo.

Cuestiones relacionadas