2015-05-14 24 views
6

cerco di manipolare un grande file CSV utilizzando Panda, quando ho scritto questoPandas leggere csv dalla memoria

df = pd.read_csv(strFileName,sep='\t',delimiter='\t') 

solleva "pandas.parser.CParserError:. Dati creazione di token errore Errore C: out of memory " wc -l indica che ci sono 13822117 linee, ho bisogno di aggregare su questo frame di dati del file csv, c'è un modo per gestire quest'altro, quindi dividere il csv in diversi file e scrivere codici per unire i risultati? Qualche suggerimento su come farlo? Grazie

L'ingresso è così:

columns=[ka,kb_1,kb_2,timeofEvent,timeInterval] 
0:'3M' '2345' '2345' '2014-10-5',3000 
1:'3M' '2958' '2152' '2015-3-22',5000 
2:'GE' '2183' '2183' '2012-12-31',515 
3:'3M' '2958' '2958' '2015-3-10',395 
4:'GE' '2183' '2285' '2015-4-19',1925 
5:'GE' '2598' '2598' '2015-3-17',1915 

E l'uscita desiderata è così:

columns=[ka,kb,errorNum,errorRate,totalNum of records] 
'3M','2345',0,0%,1 
'3M','2958',1,50%,2 
'GE','2183',1,50%,2 
'GE','2598',0,0%,1 

se il set di dati è piccolo, il codice di seguito potrebbe essere utilizzato come fornito da un'altra

df2 = df.groupby(['ka','kb_1'])['isError'].agg({ 'errorNum': 'sum', 
              'recordNum': 'count' }) 

df2['errorRate'] = df2['errorNum']/df2['recordNum'] 

ka kb_1 recordNum errorNum errorRate 

3M 2345   1   0  0.0 
    2958   2   1  0.5 
GE 2183   2   1  0.5 
    2598   1   0  0.0 

(definizione di Record errore: quando kb_1 = kb_2, il record corrispondente viene trattata come abnor mal record)

+0

Non è necessario specificare 'delimitatore' poiché' sep' è già fornito. Inoltre, 'pd.read_table()' assume 'sep = '\ t'', quindi puoi chiamarlo invece di' pd.read_csv() '. – chrisaycock

risposta

1

In base allo snippet in out of memory error when reading csv file in chunk, durante la lettura riga per riga.

Presumo che kb_2 è l'indicatore di errore,

groups={} 
with open("data/petaJoined.csv", "r") as large_file: 
    for line in large_file: 
     arr=line.split('\t') 
     #assuming this structure: ka,kb_1,kb_2,timeofEvent,timeInterval 
     k=arr[0]+','+arr[1] 
     if not (k in groups.keys()) 
      groups[k]={'record_count':0, 'error_sum': 0} 
     groups[k]['record_count']=groups[k]['record_count']+1 
     groups[k]['error_sum']=groups[k]['error_sum']+float(arr[2]) 
for k,v in groups.items: 
    print ('{group}: {error_rate}'.format(group=k,error_rate=v['error_sum']/v['record_count'])) 

Questo frammento di codice memorizza tutti i gruppi in un dizionario, e calcola il tasso di errore dopo aver letto l'intero file.

Si verificherà un'eccezione di memoria esaurita, se ci sono troppe combinazioni di gruppi.

+0

grazie, le combinazioni non sono così tante, ottengo la cosa giusta, grazie per il tuo aiuto, questa è un'ottima soluzione – sunxd

3

Non hanno dichiarato che cosa il vostro aggregazione previsto sarebbe, ma se è just sum and count, allora si potrebbe aggregare in chunks:

dfs = pd.DataFrame() 
reader = pd.read_table(strFileName, chunksize=16*1024) # choose as appropriate 
for chunk in reader: 
    temp = chunk.agg(...) # your logic here 
    dfs.append(temp) 
df = dfs.agg(...) # redo your logic here 
+0

ciao, grazie, ho modificato il mio post per aggiungere l'operazione esatta che voglio sui dati – sunxd

+0

provare: 30 dfs = pd.DataFrame() 31 reader = pd.read_table (strFileName, chunksize = 1024 * 1024 * 1024) # scelgono come appropriato 33 per chunk lettore: 34 temp = tb_createTopRankTable (chunk) 35 dfs.append (Temp) 36 df = tb_createTopRankTable (DFS) 37 eccetto: 38 traceback.print_exc (file = sys.stdout) – sunxd

+0

riga 33, nel chunckRank per il blocco nel lettore: Errore CParser: errore durante la tokenizzazione dei dati. Errore C: memoria esaurita Errore di segmentazione (core Dumped) – sunxd

2

Che @chrisaycock suggerito è il metodo preferito se è necessario somma o contare

Se avete bisogno di fare la media, non funzionerà perché avg(a,b,c,d) non è uguale avg(avg(a,b),avg(c,d))

io suggerisco di usare una mappa-reduce, come approccio, con Streaming

creare un file chiamato map-col.py

import sys 
for line in sys.stdin: 
    print (line.split('\t')[col]) 

E un file chiamato reduce-avg.py

import sys 
s=0 
n=0 
for line in sys.stdin: 
    s=s+float(line) 
    n=n+1 
print (s/n) 

E al fine di eseguire il tutto:

cat strFileName|python map-col.py|python reduce-avg.py>output.txt 

Questo metodo funziona a prescindere della dimensione del file e non esaurirà la memoria

+0

ciao, grazie, Ho modificato il mio post per aggiungere l'operazione esatta che voglio avere sui dati – sunxd

+0

puoi aiutare su una soluzione? Poiché ho incontrato difficoltà in gruppo con un file di 2.5 G, consulta http://stackoverflow.com/questions/30255986/out-of-memory-error-when-reading-csv-file-in-chunk?noredirect=1#comment48617560_30255986 – sunxd

Problemi correlati