2013-04-03 9 views
20

Ich habe etwa 7 Millionen Zeilen in einem HDFStore mit mehr als 60 Spalten. Die Daten sind mehr als ich in den Speicher passen kann. Ich versuche, die Daten in Gruppen basierend auf dem Wert einer Spalte "A" zu aggregieren. Die Dokumentation für Pandas splitting/aggregating/combining geht davon aus, dass ich alle meine Daten bereits in einem DataFrame habe, jedoch kann ich nicht den gesamten Speicher in einen In-Memory DataFrame einlesen. Was ist der richtige Ansatz zum Gruppieren von Daten in einem HDFStore?Pandas "Group By" Abfrage auf große Daten in HDFStore?

+1

haben Sie bei http://stackoverflow.com/questions/14262433/large-data sah -work-flows-using-pandas/14287518 # 14287518? Jeffs Antworten sind ein guter Grund für diese Art von Workflow –

+1

Dies wird derzeit als eine zukünftige Verbesserung für Pandas diskutiert. Ich hoffe, dass es eines Tages hinzugefügt wird, da ich SAS schließlich ablegen konnte: https://github.com/pydata/pandas/issues/3202 – Zelazny7

+0

Wie ich die Dokumentation verstehe, unterstützen HDFStores nicht alle Operationen, die auf DataFrames verfügbar sind. Sie könnten versuchen, die Fähigkeiten der Tabellenabfrage [hier] (http://pandas.pydata.org/pandas-docs/dev/io.html#query-via-data-columns) zu verwenden, um manuell jeweils eine Gruppe auszuwählen. – BrenBarn

Antwort

16

Hier ist ein komplettes Beispiel.

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) 

Ausgabe

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 

Einige Einschränkungen:

1) Diese Methode ist sinnvoll, wenn Ihre Gruppe Dichte relativ gering ist. In der Größenordnung von Hunderten oder Tausenden von Gruppen. Wenn Sie mehr als das bekommen, gibt es effizientere (aber kompliziertere Methoden), und Ihre Funktion, die Sie anwenden (in diesem Fall sum), wird restriktiver.

Im Wesentlichen würden Sie Iterator über den gesamten Speicher von Chunks, gruppieren, wie Sie gehen, aber halten Sie die Gruppen nur halb kollabiert (stellen Sie sich ein Mittelwert, so müssten Sie eine laufende Summe plus eine laufende Anzahl halten, dann teilen Am Ende). Einige Operationen wären etwas kniffliger, könnten aber VIELE Gruppen behandeln (und sind sehr schnell).

2) die Effizienz dieses durch das Speichern der Koordinaten (zB die Gruppe Standorte verbessert werden könnte, aber das ist ein bisschen komplizierter)

3) Multi-Gruppierung mit dieser Regelung nicht möglich ist (es ist möglich , erfordert aber einen Ansatz wie 2) über

4) die Spalten, die Sie gruppieren möchten, müssen eine Datenspalte sein!

5) Sie können jeden anderen Filter, den Sie wünschen, in der Auswahl BTW kombinieren (was eine schlaue Art der Multi-Gruppierung btw ist, Sie bilden nur 2 eindeutige Listen der Gruppe und Iterator über das Produkt von ihnen, nicht sehr effizient wenn Sie viele Gruppen haben, können aber funktionieren)

HTH

lassen Sie mich wissen, ob dies für Sie arbeitet

+1

Methode 2 wird hier beschrieben: https://github.com/pydata/pandas/issues/3202 – Jeff

+0

Danke Jeff.Ich würde dir Bonuspunkte geben, wenn ich dieses Beispiel (und einen Link zurück zu SO!) Zum Git-Ticket hinzufügen könnte. – technomalogical

+0

hahha .... froh zu helfen – Jeff