2013-04-03 9 views
20

Ho circa 7 milioni di righe in un HDFStore con più di 60 colonne. I dati sono più di quelli che posso inserire nella memoria. Sto cercando di aggregare i dati in gruppi in base al valore di una colonna "A". La documentazione per i panda splitting/aggregating/combining presuppone che io abbia già tutti i miei dati in un DataFrame, tuttavia non riesco a leggere l'intero archivio in una memoria in memoria DataFrame. Qual è l'approccio corretto per il raggruppamento dei dati in un HDFStore?Pandas "Raggruppa per" query su dati di grandi dimensioni in HDFStore?

+1

hai guardato http://stackoverflow.com/questions/14262433/large-data -Lavoro-flussi-con-panda/14287518 # 14.287.518? Le risposte di Jeff sono un buon primer per questo tipo di flusso di lavoro –

+1

Questo è attualmente in discussione come un miglioramento futuro per i panda. Spero davvero che venga aggiunto un giorno perché finalmente potrei abbandonare SAS: https://github.com/pydata/pandas/issues/3202 – Zelazny7

+0

Come ho capito la documentazione, HDFStores non supporta tutte le operazioni disponibili su DataFrame. Potresti provare a utilizzare le abilità di query della tabella descritte [qui] (http://pandas.pydata.org/pandas-docs/dev/io.html#query-via-data-columns) per selezionare manualmente un gruppo alla volta. – BrenBarn

risposta

16

Ecco un esempio completo.

import numpy as np 
import pandas as pd 
import os 

fname = 'groupby.h5' 

# create a frame 
df = pd.DataFrame({'A': ['foo', 'foo', 'foo', 'foo', 
         'bar', 'bar', 'bar', 'bar', 
         'foo', 'foo', 'foo'], 
        'B': ['one', 'one', 'one', 'two', 
         'one', 'one', 'one', 'two', 
         'two', 'two', 'one'], 
        'C': ['dull', 'dull', 'shiny', 'dull', 
         'dull', 'shiny', 'shiny', 'dull', 
         'shiny', 'shiny', 'shiny'], 
        'D': np.random.randn(11), 
        'E': np.random.randn(11), 
        'F': np.random.randn(11)}) 


# create the store and append, using data_columns where I possibily 
# could aggregate 
with pd.get_store(fname) as store: 
    store.append('df',df,data_columns=['A','B','C']) 
    print "store:\n%s" % store 

    print "\ndf:\n%s" % store['df'] 

    # get the groups 
    groups = store.select_column('df','A').unique() 
    print "\ngroups:%s" % groups 

    # iterate over the groups and apply my operations 
    l = [] 
    for g in groups: 

     grp = store.select('df',where = [ 'A=%s' % g ]) 

     # this is a regular frame, aggregate however you would like 
     l.append(grp[['D','E','F']].sum()) 


    print "\nresult:\n%s" % pd.concat(l, keys = groups) 

os.remove(fname) 

uscita

store: 
<class 'pandas.io.pytables.HDFStore'> 
File path: groupby.h5 
/df   frame_table (typ->appendable,nrows->11,ncols->6,indexers->[index],dc->[A,B,C]) 

df: 
     A B  C   D   E   F 
0 foo one dull -0.815212 -1.195488 -1.346980 
1 foo one dull -1.111686 -1.814385 -0.974327 
2 foo one shiny -1.069152 -1.926265 0.360318 
3 foo two dull -0.472180 0.698369 -1.007010 
4 bar one dull 1.329867 0.709621 1.877898 
5 bar one shiny -0.962906 0.489594 -0.663068 
6 bar one shiny -0.657922 -0.377705 0.065790 
7 bar two dull -0.172245 1.694245 1.374189 
8 foo two shiny -0.780877 -2.334895 -2.747404 
9 foo two shiny -0.257413 0.577804 -0.159316 
10 foo one shiny 0.737597 1.979373 -0.236070 

groups:Index([bar, foo], dtype=object) 

result: 
bar D -0.463206 
    E 2.515754 
    F 2.654810 
foo D -3.768923 
    E -4.015488 
    F -6.110789 
dtype: float64 

Alcuni avvertimenti:

1) Questa metodologia ha un senso se la densità gruppo è relativamente basso. Sull'ordine di centinaia o migliaia di gruppi. Se ottieni di più, ci sono metodi più efficienti (ma più complicati) e la tua funzione che stai applicando (in questo caso sum) diventa più restrittiva.

Sostanzialmente si eseguirà l'iteratore dell'intero negozio in base a blocchi, raggruppandoli man mano che si procede, ma mantenendo i gruppi solo parzialmente in collasso (si immagini di fare una media, quindi è necessario mantenere un totale parziale più un conteggio corrente, quindi dividere alla fine). Quindi alcune operazioni sarebbero un po 'più complicate, ma potrebbero potenzialmente gestire molti gruppi (ed è molto veloce).

2) l'efficienza di questo potrebbe essere migliorata salvando le coordinate (ad esempio le località gruppo, ma questo è un po 'più complicato)

3) multi-gruppo non è possibile con questo schema (è possibile , ma richiede un approccio più simile a 2) sopra

4) le colonne che si desidera raggruppare DEVONO essere una colonna di dati!

5) è possibile combinare qualsiasi altro filtro che si desidera nella selezione btw (che è un modo sneeky di fare multi-grouping btw, basta formare 2 liste univoche di gruppo ed iteratore sul prodotto di loro, non estremamente efficiente se hai un sacco di gruppi, ma può lavorare)

HTH

farmi sapere se questo funziona per voi

+1

metodo 2 è descritto qui: https://github.com/pydata/pandas/issues/3202 – Jeff

+0

Grazie Jeff.Ti darei punti bonus se potessi aggiungere questo esempio (e un link a SO!) Al ticket git. – technomalogical

+0

haha ​​... felice di aiutare – Jeff

Problemi correlati