2012-04-22 18 views
9

ho afferrato il TRACK1 dataset KDD da Kaggle e ha deciso di caricare un file CSV a 3 colonne ~ 2,5 GB in memoria, il mio 16GB istanza EC2 alta memoria:maggiori problemi di memoria di lettura in un file CSV utilizzando NumPy

data = np.loadtxt('rec_log_train.txt') 

la sessione python ha consumato tutta la mia memoria (100%), e poi è stata uccisa.

Ho quindi letto lo stesso file utilizzando R (tramite read.table) e ha utilizzato meno di 5 GB di RAM, che è crollato a meno di 2 GB dopo aver chiamato il garbage collector.

La mia domanda è: perché questo ha fallito in numpy, e qual è il modo corretto di leggere un file in memoria. Sì, posso usare i generatori ed evitare il problema, ma non è questo l'obiettivo.

+0

correlati http://stackoverflow.com/questions/8956832/python-out-of-memory-on-large-csv-file-numpy – Anycorn

+0

Se la precisione singola andrà bene, 'np.fromfile/np.loadtxt (dtype = np.float32) 'richiederà meno memoria, quindi' X = X.astype (np.float64) 'una volta terminato. – denis

risposta

6
import pandas, re, numpy as np 

def load_file(filename, num_cols, delimiter='\t'): 
    data = None 
    try: 
     data = np.load(filename + '.npy') 
    except: 
     splitter = re.compile(delimiter) 

     def items(infile): 
      for line in infile: 
       for item in splitter.split(line): 
        yield item 

     with open(filename, 'r') as infile: 
      data = np.fromiter(items(infile), float64, -1) 
      data = data.reshape((-1, num_cols)) 
      np.save(filename, data) 

    return pandas.DataFrame(data) 

Questa legge nel file di 2,5 GB, e serializza la matrice di uscita. Il file di input viene letto in "pigramente", quindi non vengono create strutture di dati intermedie e viene utilizzata una memoria minima. Il carico iniziale richiede molto tempo, ma ogni carico successivo (del file serializzato) è veloce. Per favore lasciami se hai suggerimenti!

+1

Se si specifica il numero di colonne a-priori, perché non fare qualcosa di più simile a questo: https://gist.github.com/2465280? Una nota a margine, per creare una matrice da un generatore, usa 'np.fromiter'. –

+0

aggiornato! Grazie mille! – vgoklani

Problemi correlati