2013-06-08 14 views
12

Ich importiere große Mengen von http-Logs (80GB +) in einen Pandas HDFStore zur statistischen Verarbeitung. Selbst innerhalb einer einzelnen Importdatei muss der Inhalt beim Laden geladen werden. Meine bisherige Taktik war es, die geparsten Zeilen in einen DataFrame zu lesen und den DataFrame dann im HDFStore zu speichern. Mein Ziel ist es, den Indexschlüssel für einen einzelnen Schlüssel im DataStore eindeutig zu machen, aber jeder DataFrame startet seinen eigenen Indexwert erneut neu. Ich hatte erwartet, dass HDFStore.append() einen Mechanismus haben würde, um zu sagen, dass er die DataFrame-Indexwerte ignoriert und einfach zu den vorhandenen Indexwerten meines HDFStore-Schlüssels hinzufügt, aber nicht gefunden werden kann. Wie importiere ich DataFrames und ignoriere die darin enthaltenen Indexwerte, während der HDFStore seine vorhandenen Indexwerte erhöht? Beispielcode unterhalb der Stapel alle 10 Zeilen. Natürlich wäre das echte Ding größer.Wie hängt man große Datenmengen an einen Pandas HDFStore an und erhält einen natürlichen eindeutigen Index?

if hd_file_name: 
     """ 
     HDF5 output file specified. 
     """ 

     hdf_output = pd.HDFStore(hd_file_name, complib='blosc') 
     print hdf_output 

     columns = ['source', 'ip', 'unknown', 'user', 'timestamp', 'http_verb', 'path', 'protocol', 'http_result', 
        'response_size', 'referrer', 'user_agent', 'response_time'] 

     source_name = str(log_file.name.rsplit('/')[-1]) # HDF5 Tables don't play nice with unicode so explicit str(). :(

     batch = [] 

     for count, line in enumerate(log_file,1): 
      data = parse_line(line, rejected_output = reject_output) 

      # Add our source file name to the beginning. 
      data.insert(0, source_name)  
      batch.append(data) 

      if not (count % 10): 
       df = pd.DataFrame(batch, columns = columns) 
       hdf_output.append(KEY_NAME, df) 
       batch = [] 

     if (count % 10): 
      df = pd.DataFrame(batch, columns = columns) 
      hdf_output.append(KEY_NAME, df) 
+0

Haben Sie [diese Antwort] (http://stackoverflow.com/a/14268804/1240268) gelesen? –

Antwort

13

Sie können es so machen. Der einzige Trick ist, dass das erste Mal, dass die Geschäftstabelle nicht existiert, get_storer wird.

import pandas as pd 
import numpy as np 
import os 

files = ['test1.csv','test2.csv'] 
for f in files: 
    pd.DataFrame(np.random.randn(10,2),columns=list('AB')).to_csv(f) 

path = 'test.h5' 
if os.path.exists(path): 
    os.remove(path) 

with pd.get_store(path) as store: 
    for f in files: 
     df = pd.read_csv(f,index_col=0) 
     try: 
      nrows = store.get_storer('foo').nrows 
     except: 
      nrows = 0 

     df.index = pd.Series(df.index) + nrows 
     store.append('foo',df) 


In [10]: pd.read_hdf('test.h5','foo') 
Out[10]: 
      A   B 
0 0.772017 0.153381 
1 0.304131 0.368573 
2 0.995465 0.799655 
3 -0.326959 0.923280 
4 -0.808376 0.449645 
5 -1.336166 0.236968 
6 -0.593523 -0.359080 
7 -0.098482 0.037183 
8 0.315627 -1.027162 
9 -1.084545 -1.922288 
10 0.412407 -0.270916 
11 1.835381 -0.737411 
12 -0.607571 0.507790 
13 0.043509 -0.294086 
14 -0.465210 0.880798 
15 1.181344 0.354411 
16 0.501892 -0.358361 
17 0.633256 0.419397 
18 0.932354 -0.603932 
19 -0.341135 2.453220 

Sie müssen eigentlich nicht einen globalen eindeutigen Index benötigen, (es sei denn, Sie einen wollen) als HDFStore (durch PyTables) stellt eine durch eindeutig Nummerierung Reihen. Sie können diese Auswahlparameter jederzeit hinzufügen.

In [11]: pd.read_hdf('test.h5','foo',start=12,stop=15) 
Out[11]: 
      A   B 
12 -0.607571 0.507790 
13 0.043509 -0.294086 
14 -0.465210 0.880798 
+0

Toller Beitrag; Es gibt Fälle (wie diese), in denen es ideal wäre, anstelle dieser Problemumgehung jedoch einen autoincrementalen Index zu verwenden. wie in: wenn Sie auf hdf5 speichern, können Sie einen ignore_index = True (wie pd.Concat) haben und dies geschieht automatisch unter der Haube? Nur eine Idee – Carst

+0

Auch: wenn große Mengen von kleinen Dateien verwendet werden, wäre es besser, zuerst die aktuelle Anzahl von Zeilen und upn jedes Mal mit der Länge des aktuellen Datenrahmens am Ende jeder Anhängen Aktion (viel besser für die Leistung)). Wenn das ein vager Kommentar ist, lass es mich wissen und ich werde es irgendwo hinarbeiten – Carst

+0

du brauchst nicht wirklich beides zu tun. Da die Geschäfte intern "nummeriert" sind, können Sie dann nach Zeilennummer wählen, wenn Sie möchten, (siehe hier) [http://pandas.pydata.org/pandas-docs/dev/io.html#advanced-queries] – Jeff

Verwandte Themen