2012-11-15 10 views
6

Sono abbastanza nuovo per Python e programmazione in generale, ma sto cercando di eseguire un calcolo "finestra scorrevole" su un file .txt delimitato da tabulazioni che contiene circa 7 milioni di righe con python . Quello che intendo per finestra scorrevole è che eseguirà un calcolo su circa 50.000 righe, riporterà il numero e poi salirà diciamo 10.000 linee e eseguirà lo stesso calcolo su altre 50.000 linee. Ho il calcolo e la "finestra scorrevole" funzionano correttamente e funziona bene se provo su un piccolo sottoinsieme dei miei dati. Tuttavia, se provo a eseguire il programma sul mio intero set di dati, è incredibilmente lento (l'ho fatto funzionare ora per circa 40 ore). La matematica è abbastanza semplice, quindi non credo che dovrebbe richiedere molto tempo.Elaborazione di un file .txt di grandi dimensioni in python in modo efficiente

Il modo in cui sto leggendo il mio file .txt adesso è con il modulo csv.DictReader. Il mio codice è il seguente:

file1='/Users/Shared/SmallSetbee.txt' 
newfile=open(file1, 'rb') 
reader=csv.DictReader((line.replace('\0','') for line in newfile), delimiter="\t") 

Credo che questo sta facendo un dizionario di tutti i 7 milioni di linee in una sola volta, che sto pensando potrebbe essere il motivo che rallenta così tanto per il file più grande.

Poiché sono interessato solo a eseguire i miei calcoli su "blocchi" o "finestre" di dati alla volta, c'è un modo più efficiente di leggere solo righe specificate alla volta, eseguire il calcolo e quindi ripetere con una nuova "porzione" o "finestra" specificata di linee specificate?

+1

Questo non rende un dizionario di tutte le linee contemporaneamente. Crea un dizionario per ogni riga. Ciò significa che lo snippet che hai pubblicato non è la causa dei tuoi problemi di prestazioni. Forse potresti mostrarci un altro codice? –

+1

Sospetto che se stai facendo calcoli su ampi set di dati simili a tabelle potresti voler dare un'occhiata a Pandas: http://pandas.pydata.org/pandas-docs/dev/io.html#iterating-through- files-chunk-by-chunk Tutto quello che stai cercando di fare probabilmente è già stato fatto prima di 1000 volte meglio. – Iguananaut

+0

Esegui questo calcolo su 696 "finestre". Quanto tempo ci vuole per una singola finestra su un file di 50k line? –

risposta

6

A collections.deque è una raccolta ordinata di elementi che possono richiedere una dimensione massima. Quando aggiungi un oggetto a un'estremità, una cade dell'altra estremità. Ciò significa che per iterare su una "finestra" sul tuo csv, devi semplicemente aggiungere righe allo deque e gestirà già il lancio di quelle complete.

dq = collections.deque(maxlen=50000) 
with open(...) as csv_file: 
    reader = csv.DictReader((line.replace("\0", "") for line in csv_file), delimiter="\t") 

    # initial fill 
    for _ in range(50000): 
     dq.append(reader.next()) 

    # repeated compute 
    try: 
     while 1: 
      compute(dq) 
      for _ in range(10000): 
       dq.append(reader.next()) 
    except StopIteration: 
      compute(dq) 
+1

'try/except' dovrebbe essere più vicino a' reader.next() 'per evitare cattura accidentalmente 'StopIteration' da' compute (dq) ' – jfs

3

Non utilizzare csv.DictReader, utilizzare invece csv.reader. Ci vuole più tempo per creare un dizionario per ogni riga di quanto ci vuole per creare un elenco per ogni riga. Inoltre, è leggermente più veloce accedere a un elenco tramite un indice piuttosto che accedere a un dizionario tramite una chiave.

I iterazione temporizzata su un file csv a 300.000 righe 4 colonne utilizzando i due lettori csv. csv.DictReader ha richiesto sette volte più lungo rispetto a csv.reader.

Combina questo con katrielalex's suggestion per utilizzare collections.deque e dovresti vedere una bella accelerazione.

Inoltre, profile il codice per individuare dove si trascorre la maggior parte del tempo.