2011-01-27 5 views
15

Attualmente stiamo utilizzando ZedGraph per disegnare un grafico a linee di alcuni dati. I dati di input provengono da un file di dimensioni arbitrarie, pertanto, non sappiamo in anticipo quale sia il numero massimo di punti dati. Tuttavia, aprendo il file e leggendo l'intestazione, possiamo scoprire quanti punti di dati ci sono nel file.Creazione di enormi quantità di dati

Il formato del file è essenzialmente [tempo (doppio), valore (doppio)]. Tuttavia, le voci non sono uniformi nell'asse del tempo. Potrebbero non esserci punti tra say t = 0 sec e t = 10 sec, ma potrebbero esserci 100K entrate tra t = 10 sec e t = 11 sec, e così via.

Ad esempio, il nostro file del set di dati di test è ~ 2,6 GB e ha 324 milioni di punti. Vorremmo mostrare l'intero grafico all'utente e farle navigare nel grafico. Tuttavia, caricare fino a 324 milioni di punti su ZedGraph non solo è impossibile (siamo su una macchina a 32 bit), ma non è neanche utile dato che non ha senso avere così tanti punti sullo schermo.

Anche l'utilizzo della funzione FilteredPointList di ZedGraph sembra essere fuori questione, poiché è necessario caricare prima tutti i dati e quindi eseguire il filtraggio su tali dati.

Quindi, a meno che non ci manca niente, sembra che la nostra unica soluzione è quella di -somehow- decimare i dati, tuttavia, come continuiamo a lavorare su di esso, stiamo correndo in un sacco di problemi:

1- Come decimiamo i dati che non arrivano in modo uniforme in tempo?

2- Poiché non è possibile caricare in memoria tutti i dati, è necessario che qualsiasi algoritmo funzioni sul disco e pertanto deve essere progettato con attenzione.

3- Come si gestisce lo zoom in entrata e in uscita, soprattutto quando i dati non sono uniformi sull'asse x.

Se i dati erano uniformi, al caricamento iniziale del grafico, è possibile immettere Seek() in base alla quantità predefinita di voci nel file e scegliere ogni N altri campioni e inviarlo a ZedGraph. Tuttavia, poiché i dati non sono uniformi, dobbiamo essere più intelligenti nella scelta dei campioni da visualizzare e non possiamo trovare alcun algoritmo intelligente che non debba leggere l'intero file.

Mi scuso perché la domanda non ha specificità taglienti, ma spero di poter spiegare la natura e la portata del nostro problema.

Siamo su Windows a 32 bit, .NET 4.0.

risposta

8

Ho avuto bisogno di questo prima, e non è facile da fare. Ho finito per scrivere il mio componente grafico a causa di questo requisito. Alla fine è andata meglio, perché ho inserito tutte le funzionalità di cui avevamo bisogno.

Fondamentalmente è necessario ottenere l'intervallo di dati (minimo e massimo possibile/necessario valori dell'indice), suddividere in segmenti (diciamo 100 segmenti) e quindi determinare un valore per ogni segmento con un algoritmo (valore medio, mediana valore, ecc.). Quindi trama in base a questi 100 elementi riassunti. Questo è molto più veloce di cercare di tracciare milioni di punti :-).

Quindi quello che sto dicendo è simile a quello che stai dicendo. Si cita che non si desidera tracciare ogni elemento X perché potrebbe esserci un lungo intervallo di tempo (valori dell'indice sull'asse x) tra gli elementi. Quello che sto dicendo è che per ogni suddivisione dei dati si determina quale sia il valore migliore e si consideri il punto dati. Il mio metodo è basato sul valore dell'indice, quindi nel tuo esempio di nessun dato tra i valori dell'indice di 0 sec e 10 sec metterei comunque i punti di dati lì, avrebbero solo gli stessi valori tra loro.

Il punto è di riepilogare i dati prima di tracciarli. Pensa attraverso i tuoi algoritmi per farlo con attenzione, ci sono molti modi per farlo, scegli quello che funziona per la tua applicazione.

Si potrebbe ottenere senza scrivere il proprio componente grafico e basta scrivere l'algoritmo di riepilogo dei dati.

+0

Concordato sul tuo ultimo punto. Riassumere adeguatamente i dati allevierà il mal di testa della visualizzazione di x # di scenari. –

+0

gmagana: Sì, penso che suona come un modo per andare. Sono solo preoccupato che ogni volta che l'utente vuole ingrandire o rimpicciolire, dovremo rileggere e riassumere il file. Abbiamo pensato ad alcuni algoritmi di memorizzazione nella cache, ma poiché in qualsiasi momento i dati sul grafico saranno decimati, il caching di quei punti potrebbe non avere senso. – SomethingBetter

+0

@SomethingBetter: Sì, lo zoom è uno dei motivi per cui ho scritto il mio. Avevamo bisogno di qualcosa come il grafico di Google Finance (ad esempio, http://www.google.com/finance?q=msft), quindi l'ho scritto da zero. –

3

1- Come si decimano i dati che non sono che arrivano uniformemente in tempo?

(Nota -. Sto assumendo il vostro file di dati caricatore è in formato testo)

su un progetto simile, ho dovuto leggere file di dati che sono stati più di 5 GB di dimensione. L'unico modo per analizzarlo era leggerlo in una tabella RDBMS. Abbiamo scelto MySQL perché rende semplice l'importazione di file di testo in datatables. (Un lato interessante - ero su una macchina Windows a 32 bit e non potevo aprire il file di testo per la visualizzazione, ma MySQL non lo leggeva.) L'altro vantaggio era che MySQL era urlando, urlando velocemente.

Una volta che i dati erano nel database, potremmo facilmente ordinarli e quantificare grandi quantità di dati in singole query parafrasate (usando funzioni di sommario SQL incorporate come SUM). MySQL potrebbe persino leggere i risultati della query in un file di testo da utilizzare come dati del caricatore.

Per farla breve, consumare così tanti dati richiede l'uso di uno strumento in grado di riepilogare i dati. MySQL è la soluzione ideale (il gioco di parole è ... gratuito).

+0

È interessante, inserire tutti questi dati nel database per primo potrebbe essere un sacco di tempo, ma suppongo che se analizzeremo gli stessi dati più e più volte, potrebbe essere d'aiuto. Anche se, questo non aiuta affatto con il nostro problema fondamentale: come leggere questi dati, riassumere in un numero ragionevole di punti e mostrare nel grafico. - grazie – SomethingBetter

4

vorrei affrontare questo in due fasi:

  1. pre-elaborazione dei dati
  2. Visualizzazione dei dati

Fase 1 Il file deve essere pre-elaborato in un file di formato fisso binario. Aggiungendo un indice al formato, sarebbe int, double, double. veda questo articolo per il confronto di velocità:

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

È quindi possibile suddividere il file in intervalli di tempo, diciamo uno per ogni ora o giorno, che vi darà un modo semplice per esprimere accesso momento diverso intervalli. Si potrebbe anche solo mantenere un unico grande file e avere un file indice che ti dice dove trovare momenti specifici,

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

utilizzando uno di questi metodi si sarà in grado di trovare rapidamente qualsiasi blocco dei dati da una volta, attraverso un nome di indice o di un file, o per numero di voci, a causa del formato fisso di byte .

Passaggio 2 Metodi per mostrare i dati 1. Basta visualizzare ciascun record per indice. 2. Normalizza i dati e crea barre di dati aggregati con valori di apertura, alta, bassa, chiusura. a. Per tempo b.Con numero di record c. Per differenza tra il valore

Per ulteriori possibili metodi di aggregazione di set di dati non uniformi, è possibile esaminare i metodi diversi per l'aggregazione dei dati commerciali nei mercati finanziari. Naturalmente, per la velocità in tempo reale, il rendering che si desidera creare file con questi dati già aggregati.

+0

L'articolo codeproject è stato interessante, grazie. – SomethingBetter

0

Un relativamente facile alternativa che ho trovato per farlo è quello di effettuare le seguenti operazioni:

  1. Scorrere i dati in raggruppamenti di punti di piccole dimensioni (ad esempio da 3 a 5 punti in un momento - più grande è il gruppo, più veloce sarà l'algoritmo ma meno accurata sarà l'aggregazione).
  2. Calcolare il minimo & del piccolo gruppo.
  3. Rimuovere tutti i punti che sono non il minimo o il massimo da quel gruppo (cioè si mantengono solo 2 punti per ciascun gruppo e si omette il resto).
  4. Continua a scorrere i dati (ripetendo questo processo) dall'inizio alla fine, rimuovendo i punti fino a quando il set di dati aggregati ha un numero sufficientemente piccolo di punti in cui può essere tracciato senza strozzare il PC.

Ho usato questo algoritmo in passato per portare set di dati di ~ 10 milioni di punti nell'ordine di ~ 5K punti senza alcuna evidente distorsione visibile al grafico.

L'idea è che, mentre si eliminano i punti, si conservano i picchi e le valli in modo che il "segnale" visualizzato nel grafico finale non sia "mediato in basso" (normalmente, se si calcola la media, vedrete le vette e le valli diventano meno prominenti).

L'altro vantaggio è che si vedono sempre punti "reali" sul grafico finale (mancano un sacco di punti, ma i punti che c'erano erano effettivamente nel set di dati originale quindi, se si passa il mouse su qualcosa, puoi mostrare i valori effettivi x & y perché sono reali, non mediati).

Infine, questo aiuta anche a non avere una spaziatura costante dell'asse x (di nuovo, avrete punti reali invece di calcolare la media delle posizioni dell'asse X).

Non sono sicuro di quanto questo approccio possa funzionare con 100 milioni di punti dati come te, ma potrebbe valere la pena provare.