2013-06-08 9 views
12

Importuję duże ilości dzienników http (80 GB +) do Pandas HDFStore w celu przetworzenia statystycznego. Nawet w pojedynczym pliku importu muszę wsadową zawartość, gdy ją ładuję. Moja dotychczasowa taktyka polegała na czytaniu analizowanych linii w DataFrame, a następnie przechowywaniu DataFrame w HDFStore. Moim celem jest posiadanie unikalnego klucza indeksu dla pojedynczego klucza w DataStore, ale każda DataFrame ponownie uruchamia swoją własną wartość indeksu. Oczekiwałem, że HDFStore.append() będzie miał jakiś mechanizm, który powie mu, aby zignorował wartości indeksu DataFrame i po prostu dodaje do moich wartości indeksu klucza pliku HDFStore, ale nie może go znaleźć. Jak zaimportować DataFrame i zignorować zawarte w nich wartości indeksu, podczas gdy HDFStore zwiększa swoje istniejące wartości indeksu? Przykładowy kod poniżej partii co 10 linii. Naturalnie prawdziwa rzecz byłaby większa.W jaki sposób można dołączyć duże ilości danych do Pandas HDFStore i uzyskać naturalny unikalny indeks?

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

Czy znasz [tę odpowiedź] (http://stackoverflow.com/a/14268804/1240268)? –

Odpowiedz

13

Możesz to zrobić tak. Jedyną sztuczką jest to, że po raz pierwszy tabela magazynu nie istnieje, więc podbije.

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 

rzeczywiście nie muszą globalny indeks unikatowy, (chyba, że ​​chcesz jeden) jako HDFStore (poprzez PyTables) stanowi jeden po wyjątkowo numeracji wierszy. Zawsze możesz dodać te parametry wyboru.

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

Świetny post; istnieją przypadki (takie jak te), w których idealnym rozwiązaniem byłoby posiadanie indeksu autoinkreacyjnego zamiast tego obejścia. jak w: kiedy zapisujesz na hdf5, możesz mieć ignore_index = True (jak pd.Concat) i robi to automatycznie pod maską? Pomysł: – Carst

+0

Ponadto: przy korzystaniu z dużych ilości małych plików, lepiej najpierw uzyskać bieżącą liczbę wierszy i wyższą za każdym razem z długością bieżącej ramki danych na końcu każdej akcji dołączenia (znacznie lepiej dla wydajności). Jeśli jest to niejasny komentarz, daj mi znać, a ja go wymyślę gdzieś, – Carst

+0

tak naprawdę nie musisz robić żadnej z tych rzeczy. ponieważ sklepy są "ponumerowane" wewnętrznie, możesz wybrać numer wiersza, jeśli chcesz, (patrz tutaj) [http://pandas.pydata.org/pandas-docs/dev/io.html#advanced-queries] – Jeff

Powiązane problemy