2012-03-22 7 views
9

Un mio amico deve leggere un sacco di dati (circa 18000 set di dati) che è tutto formattato in modo fastidioso. In particolare, i dati dovrebbero essere 8 colonne e ~ 8000 righe di dati, ma i dati vengono invece consegnati come colonne di 7 con l'ultima voce che si riversa nella prima colonna della riga successiva.Python: Come leggere un file di dati con un numero irregolare di colonne

Inoltre ogni ~ 30 righe ci sono solo 4 colonne. Questo perché alcuni programmi upstream stanno rimodellando un array 200 x 280 nell'array 7x8120.

La mia domanda è questa: come possiamo leggere i dati in un array 8x7000. Il mio solito arsenale di np.loadtxt e np.genfromtxt fallisce quando c'è un numero irregolare di colonne.

Tenere presente che le prestazioni sono un fattore in quanto ciò deve essere fatto per ~ 18000 file di dati.

Ecco un collegamento a un tipico file di dati: http://users-phys.au.dk/hha07/hk_L1.ref

+0

Per chiarire: ogni 24 righe c'è una riga di 4 colonne a causa del continuo "traboccare" delle otto colonne in ogni riga successiva. Destra? Ogni blocco di 24 * 7 + 4 ha 200 elementi, che è equamente divisibile per 8. –

+1

Un esempio sarebbe molto utile. –

+1

Che ne dici di correggere il programma upstream per produrre file HDF5 belli, o almeno qualcosa di meno folle di questo? –

risposta

11

Un approccio ancora più semplice Ho solo pensato di:

with open("hk_L1.ref") as f: 
    data = numpy.array(f.read().split(), dtype=float).reshape(7000, 8) 

Questa legge i dati come un array monodimensionale prima, ignorando completamente tutti i caratteri di nuova riga, e poi ci ridisegnarlo alla forma desiderata.

Mentre penso che il task verrà comunque associato all'I/O, questo approccio dovrebbe impiegare poco tempo processore se è importante.

0

ne dici di questo?

data = [] 
curRow = [] 
dataPerRow = 8 
for row in FILE.readlines(): 
    for item in row.split(): 
     if len(curRow) == dataPerRow: 
      data.append(curRow) 
      curRow = [] 
     curRow.Append(item) 

data.append(curRow) 

(FILE supponendo che è il file in fase di lettura in) Devi quindi una lista di liste, che possono essere utilizzati per qualsiasi cosa.

1

a condizione che ho capito bene (vedi il mio commento) è possibile dividere il tuo ingresso in gettoni, poi elaborarlo in blocchi di otto indistintamente:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

f = open('filename.ref') 
tokens = f.read().split() 

rows = [] 
for idx, token in enumerate(tokens): 
    if idx % 8 == 0: 
     # this is a new row, use a new list. 
     row = [] 
     rows.append(row) 
    row.append(token) 

# rows is now a list of lists with the desired data. 

Questo viene eseguito in meno di 0,2 secondi nel mio computer come è.

Modifica: usato suggerimento di @SvenMarnach.

+0

Perché stai usando 'shlex' qui? Un semplice 'str.split()' farebbe il trucco. –

+0

@SvenMarnach: Ho pensato che fosse più semplice in quanto presenta un flusso infinito di token dal file. Con 'line.split()' dovrei scorrere il file personalmente, tenendo traccia dell'offset attuale a causa del problema 8-column-in-7 descritto dall'OP. O quello o scrivi un generatore, immagino, ma è più o meno quello che uso qui per Shlex. Se non lo sto seguendo, fatemelo sapere! –

+0

Basta usare 'f.read(). Split()', e hai finito. –

Problemi correlati